|
|
|
Две тр-ции хотят update одной строки: может ли быть deadlock вместо concurrent_transaction
|
|||
|---|---|---|---|
|
#18+
hi all Есть табличка, играющая роль "семафора". В ней - одна запись, которую должна залочить транзакция, если собирается далее выполнять код, который должен в конкуретном окружении выполняться всегда строго одной транзакцией или вообще никем. И есть ХП (её имя - sp_try_lock_record), которая получает на вход имя таблицы и значение ID'шника, а делает при этом следующее (почти псевдокод): Код: 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. 49. 50. 51. 52. 53. 54. Эта ошибка имеет мнемону = "concurrent_transaction", её код = 335544878. Пробные запуски в двух isql'ях также показывали, что возникает именно ЭТА ошибка и ХП пишет именно её номер в лог. А теперь вопрос. Как такое может быть, что в этой ХП возникает НЕ concurrent_transaction, а deadlock ? При условии, конечно же, что две транзакции лезут только за одной записью в одну и ту же таблицу. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.04.2014, 02:31:31 |
|
||
|
Две тр-ции хотят update одной строки: может ли быть deadlock вместо concurrent_transaction
|
|||
|---|---|---|---|
|
#18+
Таблоид, во-первых, "мнемона" concurrent_transaction это вторичный код ошибки (номер транзакции-конкурента), первичный код должен быть update_conflict. Во-вторых, для дедлока нужен всего-навсего встречный (в разном направлении) последовательный апдейт двух записей. С одной записью он если и вылезет когда-либо, то только в случае ошибки лок-менеджера или кеш-менеджера (вместе с lock conversion denied). Закладывать на это логику ХП никакого смысла не имеет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.04.2014, 10:17:37 |
|
||
|
Две тр-ции хотят update одной строки: может ли быть deadlock вместо concurrent_transaction
|
|||
|---|---|---|---|
|
#18+
dimitrво-первых, "мнемона" concurrent_transaction это вторичный код ошибки (номер транзакции-конкурента), первичный код должен быть update_conflict. Во-вторых, для дедлока нужен всего-навсего встречный (в разном направлении) последовательный апдейт двух записей. С одной записью он если и вылезет когда-либо, то только в случае ошибки лок-менеджера или кеш-менеджера (вместе с lock conversion denied). Закладывать на это логику ХП никакого смысла не имеет.Вроде бы понятно. Хотя и не очень. Если сделать так: 1) создать таблицу в 1 строку, которая залочена сессией #1 : Код: plaintext 1. 2. 2) выполнить execute block, запускаемый сессией #2: Код: 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. - то результат вып-я этого кода будет: Код: plaintext 1. 2. 3. 4. 5. То же самое, выполняемое просто как команды в isql: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. Т.е. "update conflicts" всё таки есть, но он почему-то спрятался за дедлоком. Который непонятно, с какого будуна лезет :-/ ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.04.2014, 13:42:31 |
|
||
|
Две тр-ции хотят update одной строки: может ли быть deadlock вместо concurrent_transaction
|
|||
|---|---|---|---|
|
#18+
ТаблоидТ.е. "update conflicts" всё таки есть, но он почему-то спрятался за дедлоком да, все именно так. И будет так оставаться, к сожалению (из-за обратной совместимости). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.04.2014, 14:24:43 |
|
||
|
Две тр-ции хотят update одной строки: может ли быть deadlock вместо concurrent_transaction
|
|||
|---|---|---|---|
|
#18+
А тогда еще вопросик. Вот такой блок, с двумя when-блоками: Код: 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. - выдаёт (при обломе залочить запись): Код: plaintext 1. 2. И ничего не выдаёт на гор а саспендом. То же самое, если заменить select for update на "просто" update. Это бага или так и должно быть ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.04.2014, 14:32:47 |
|
||
|
Две тр-ции хотят update одной строки: может ли быть deadlock вместо concurrent_transaction
|
|||
|---|---|---|---|
|
#18+
... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.04.2014, 14:54:21 |
|
||
|
Две тр-ции хотят update одной строки: может ли быть deadlock вместо concurrent_transaction
|
|||
|---|---|---|---|
|
#18+
Да, и еще тут нарыл. Может, так и должно быть, но странно как-то. DDL: Код: 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. 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. Test: Код: plaintext 1. 2. 3. 4. 5. 6. 7. Код: plaintext 1. 2. 3. 4. Очень хорошо. А теперь смотрим в лог: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 1) Откудова там записи с "smth else happens on iter = ..." ? Разве не должен был when any отработать ТОЛЬКО в случае, ели исключение НЕ попало в список, указанный в ПЕРВОМ when-блоке (который "when gdscode concurrent_transaction, gdscode" deadlock) ? 2) Если даже допустить, что when any отрабатывает всегда (т.е. так, как в Сишном switch при забытом break управление идёт в след. case), то почему он отрабатывал пять раз, а "красный" exception - ни одного ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.04.2014, 15:07:30 |
|
||
|
|

start [/forum/topic.php?fid=40&msg=38613979&tid=1563695]: |
0ms |
get settings: |
7ms |
get forum list: |
9ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
166ms |
get topic data: |
6ms |
get forum data: |
2ms |
get page messages: |
26ms |
get tp. blocked users: |
1ms |
| others: | 219ms |
| total: | 440ms |

| 0 / 0 |
