|
|
|
mon$context_variables - пример для проверок непересек. диапазонов c "dirty reads"
|
|||
|---|---|---|---|
|
#18+
hi all. Что-то интересно было бошку поломать над вот этим: http://www.sql.ru/forum/1075333/kak-izbezhat-peresekaushhihsya-otrezkov-vremeni-v-tablice В итоге, случилось следующее. DDL: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. В таблицу `t` добавлено поле tid, в которое всегда пишется current_transaction. Это поле нужно для различения транзакцией "своих" и "чужих" записей. Когда аттач добавляет/меняет в рамках одной транзакции одну или несколько записей таблицы `t`, то срабатывание after-триггера приведет к merge в таблицу mon$context_variables записей: MON$ATTACHMENT_IDMON$TRANSACTION_IDMON$VARIABLE_NAMEMON$VARIABLE_VALUE993F1_NEW1300993F1_NEW2100993F1_NEW350993F2_NEW1400993F2_NEW2200993F2_NEW3500993ID_NEW11993ID_NEW22993ID_NEW33 - для трёх стейтментов вида: Код: plaintext 1. 2. Независимо от того, работает ли один аттач или у него есть конкуренты, меняющие поля f1 & f2 на недопустимые значения, запрос вида: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. - выдаст непустое множество. СТЕ-часть этого запроса выглядит так (для тех же трёх стейтментов):TIDVNCTX_OPMODECTX_ID_NEWCTX_F1_NEWCTX_F2_NEW1089_NEW113004001089_NEW221002001089_NEW3350500- и мы ищем среди этих строк те, что пересекаются по f1...f2. Для поиска оных применяется широко известная в узких кругах формула: произведение разностей "координат" (a-d) * (c-b) отрезков [a...b] & [c...d] должно быть положительным числом. Функция sign() - просто перестраховка от num overflow при перемножении. Разумеется, это будет так только если с базой работает SYSDBA или её владелец. Иначе выборка останется пустой: "чужие" данные mon$context_variables не видны непривилегированным юзерам. Таким обр, можно отловить попытку изменения полей на "плохие" диапазоны, пересекающиеся либо с диапазонами этого же аттача, либо незакоммиченными значениями аттачей-конкурентов. Что касается проверки наличия закоммиченных диапазонов, пересекающихся с записями, изменёнными в текущей транзакции, то это отлавливается примерно так же: выборка Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. - должна быть пустой, иначе есть проблемы с пересечением. Проверял без особого пристрастия: просто открыл одно, затем два окна, и вводил разные данные (на "силовой установке" с 300 коннектами проверку не делал :)). test #1. Работа в одном окне. Транзакция пытается ввести несколько записей, в числе которых есть пересекающиеся диапазоны f1 & f2. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. test #2. Работа в одном окне. Транзакция вводит сначала непересекающиеся диапазоны, а затем апдейтит поля f1 & f2 - увеличивает их на одно и то же значение. Новые диапазоны будут пересекаться с ПРЕЖНИМИ в рамках одной записи, однако они не будут пересекаться "между" записями. То есть, COMMIT должен пройти успешно: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. test #3. Работа в двух окнах. Транзакции стартуют одновременно и вводят "плохие" диапазоны Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. test #4. Работа в двух окнах. Транзакция-1 успевает делать commit до того, как транзакция-2 изменит данные на "плохой диапазон". Транзакция-2 должна обломиться. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. Вроде бы работает, но... сомнения есть, что тут всё пучком. Покритикуйте, плз. Или дайте контр-пример. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.02.2014, 18:55:11 |
|
||
|
mon$context_variables - пример для проверок непересек. диапазонов c "dirty reads"
|
|||
|---|---|---|---|
|
#18+
Проверил силовым методом на 2.5 - вроде бы работает ОК. Создал пару вспом. вьюх: V_CROSS_M Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. V_CROSS_T Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. А также скрипт, который вставляет в таблицу 1000 "пакетов" записей, каждый из которых содержит 20 строк с непересекающимися диапазонами f1...f2: cross.sql Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. Однако, он добавляет эти "пакеты" в случайном порядке (insert into t ... select from .... order by rand()). Каждый пакет (20 строк) добавляется в автономной транзакции. При обломе внутри триггера на COMMIT исключение будет задушено, чтобы скрипт мог продолжать свою работу до упора. Запускаю 30 isql'ей: Код: plaintext 1. 2. 3. 4. По окончании их работы делаю коннект и подсчет строк из вьюхи v_cross_t - результат д.б. равен 0, что соблюдается. Но! Идиллия закончилась при проверке на LI-T3.0.0.30872: запрос select count(*) from mon$context_variables, введенный при запущенных 30 isql'ях, взвис наглухо . ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.02.2014, 22:42:25 |
|
||
|
mon$context_variables - пример для проверок непересек. диапазонов c "dirty reads"
|
|||
|---|---|---|---|
|
#18+
бНОПНЯ! Вот такой набор стейтментов, вводимых в одну строку в isql: Код: plaintext - выполняется в ФБ-3 достаточно долго, минут 5. Однако, я вижу издевательски одинаковые значение таймштампа (и такое же глумливое elapsed time): Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. Про elapsed time = 0.02 - это один вопрос. Но что там с current_timestamp: он-то почему вывелся так, словно был выполнен execute block ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.02.2014, 23:14:20 |
|
||
|
|

start [/forum/topic.php?fid=40&fpage=103&tid=1563918]: |
0ms |
get settings: |
7ms |
get forum list: |
14ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
64ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
34ms |
get tp. blocked users: |
1ms |
| others: | 201ms |
| total: | 336ms |

| 0 / 0 |
