Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
Доброго дня! На форуме уже не один вопрос по данной теме, но ни в одной теме (как и нигде в офф документации) не могу найти четкого ответа - какие ошибки могут стать причиной перехода транзакции в состояние нефиксируемой, почему это состояние возникает, где можно об этом подробно почитать? Ошибки DDL и XACT_STATE ON не принимаю во внимание - с ними более менее понятно, но что с остальными случаями? Набросал небольшой пример на основе реальных хранимок, которые сваливаются с ошибкой: Код: plaintext Вот текст: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. Во внешей хранимке открывается транзакция, внутренняя хранимка генерит исключение преобразования типов (которое никоим образом на самой транзакции не отражается). Однако XACT_STATE() в блоке CATCH уже показывает на "-1". Почему так? Сразу вброшу более практически обоснованный пример (с которым, собственно, и мучаюсь сейчас) - есть внешняя хранимка, которая перебирает в цикле определенные записи и коммитит обработки блоками по N штук. Саму обработку отдельной записи выполняет внутренняя хранимка (вызываемая из внешней) и для нее ошибка во входных данных должна быть обычным делом, не влияющим на результаты обработки остальных записей и, соответственно - на возможность закоммитить корректно обработанные записи. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2017, 17:20 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
Ceib, Использование конструкции TRY...CATCH в языке Transact-SQL см Нефиксируемые транзакции ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2017, 17:31 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
buser, Это внимательно изучил, причем неоднократно - так сказать для лучшего усвоения) Здесь нет ответа на вопрос. Формулировки расплывчатые и без конкретики: "транзакции могут переходить в состояние, в котором транзакция остается открытой, но не может быть зафиксирована" - это мы и так понимаем, раз ошибку получили, нам интересно почему и в каких случаях это происходит, чтобы предусмотреть это в своем коде; "транзакция переходит в нефиксируемое состояние, если внутри блока TRY происходит ошибка, которая в других обстоятельствах завершила бы эту транзакцию" - какие именно ошибки могут спровоцировать переход в это состояние? - без этого знания мы не сможем предусмотреть корректное поведение "...в результате большинства ошибок, вызываемых инструкциями языка DDL...", "когда значение параметра SET XACT_ABORT установлено в ON" - об этом писал, что более менее понятно. Интересуют остальные (совсем не очевидные) случаи Про проверку XACT_STATE - тоже понятно, что она даст нам информацию о текущем состоянии, но если в конкретной задаче крайне важно этого состояния избежать, то что делать? Все таки вопрос про конкретику у меня возник. Хотя бы и на том примере, что привел - ПОЧЕМУ там возникает эта ошибка? Как влияет ошибка преобразования типов нейтральных локальных переменных на всю транзакцию и как не потерять изменения транзакции при возникновении таких "левых" ошибок? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2017, 17:42 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
CeibВо внешей хранимке открывается транзакция, внутренняя хранимка генерит исключение преобразования типов (которое никоим образом на самой транзакции не отражается). Однако XACT_STATE() в блоке CATCH уже показывает на "-1". Почему так?Потому что у вас XACT_ABORT = ON. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2017, 17:47 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
invm, Нет, у меня XACT_ABORT = OFF. По умолчанию XACT_ABORT = OFF, поэтому в коде явно не прописал установку. Повторяю код с установкой параметра: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. Ошибка никуда не делась. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2017, 17:51 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
Ceib, не нашел в мсдн... где-то на форуме уже было... Errors Raised with Severity/Level 16 May Cause Transactions into Doomed State ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2017, 18:15 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
Ceib, ну так а что вы хотели, у вас ошибка откатывающая транзакцию возникает во внутренней процедуре, но там у вас блока try_catch нет. соответственно у вас откатывается транзакция в процедуре test_inner, и вы выходите из нее с @@trancount уже не тем с которым в нее зашли. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2017, 18:20 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
Ceib, что бы не было ошибки у вас должно быть что то типа такого: Код: 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. не беря в расчет что по хорошему вам еще на входе внешней процедуры необходимо анализировать @@trancount, иначе вся эта красота развалится при входе во внешнюю хп с TC>0 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.12.2017, 18:30 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
во общем случае никак. Потому что точного списка ошибок нет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2017, 10:06 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
felix_ff Как писал выше - есть необходимость обходиться без откатов и обязательно фиксировать уже внесенные ранее в транзации изменения. Вопрос в том, что нет понимания логики - почему ошибки никоим образом не влияющие на саму транзакцию (в данном случае - операции надо локальными переменными) фактически убивают эту транзакцию и обработать это (продолжить работу транзакции без отката) невозможно. Поправьте меня, если не прав. buser, Спасибо за ссылку - интересная заметка. Исходя из последнего абзаца: "I have written this blog as it is not possible to write every example and scenario in the official documentation. I have tested the above example in-house and reached to this conclusion. There could be lot more errors that may get the transactions into doomed state! The user could refer to this blog as a reference to identify whether the error raised with severity\level 16 would roll back the transaction or not. If you wish you can also test errors with other severities or levels." - предполагаю, что в официальной документации действительно не описано, как однозначно классифицировать ошибки, приводящие к нефиксируемому состоянию и догадываться нужно самим. Печально) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2017, 10:08 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
а вот тут есть рекомендация )) если таки у вас есть блоки "важного кода" то оборачивать в try cath только их, а не ставить try cath в верхней процедуре и надеяться что всё "заработает" само )). И таки надо понимать что к чему в транзакциях. Это к тому что а может "важный код" вынести из транзакции - и целостность проверять ручками?)) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2017, 10:22 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
dao, Честно говоря, не совсем Вас понял. Что понимается под "важным кодом" и о какой именно целостности идет речь? Признаюсь - с MSSQL работаю не так давно и мое представление о внутренностях транзакций в ней может быть неполным. И задача сейчас стоит по переносу одной разработки из другой большой СУБД в MSSQL. Конкретно - есть табличка с CSV-строчками, нужно эти CSV распарсить и положить в таблицу сущности. Если парсинг неудачен (данные на входе могут быть некорректны), то просто игнорировать эту строчку исходной таблицы с продолжением работы над остальными. Сделать все это надо с минимальным количеством транзакций (если строк исходной таблицы относительно немного - можно и одной обойтись). Приведу код (постараюсь его сократить максимально для более простого восприятия): Код: 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. Какую часть здесь можно вынести из транзакции? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2017, 11:05 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
Ceib не могу найти четкого ответа - какие ошибки могут стать причиной перехода транзакции в состояние нефиксируемой Например вот такого рода. Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2017, 11:22 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
Код: 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. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2017, 11:33 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2017, 11:45 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
Также нарушение констрейнта, и, кажется, отсутствие объекта во вложенной процедуре. Всё, память и фантазия иссякла. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2017, 11:47 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
CeibЕсли парсинг неудачен (данные на входе могут быть некорректны), то просто игнорировать эту строчку исходной таблицы с продолжением работы над остальными.Версия SQL Server какая? Если >= 2012. то см. функции try_parse, try_cast, try_convert. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2017, 12:06 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
Ceib, ну так вы и сами себе ответили )) А зачем в верхней проце запускаете транзакцию? )) try catch вообще то не связан с транзакцией и ничего не стоит запускать его вне транзакции )) а с учетом авторОшибка преобразования типов является нормальным поведением для нее try catch надо ставить в нижней процедуре. Не зная полных условий задачи , не могу вам советовать с 100% достоверностью - но в вашей задаче транзакция вообще не нужна, а может вообще противопоказана )). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2017, 12:07 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
invm, Спасибо за подсказку, поставил try_cast'ы - для данной задачи это то, что нужно. dao, Транзакция нужна здесь не потому что логически нужно обрабатывать блок как единое целое, не для сохранения консистентности даже, а для оптимизации производительности (минимизации операций с диском). Вариант без оборачивания всего этого добра транзакцией дает достаточно большую нагрузку на диск, не говоря уже о, как следствие, значительно большем времени выполнения скрипта. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2017, 12:57 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
Ceib, Если таки вы знаете как может транзакция "минимизации операций с диском" может поделитесь знаниями? ) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2017, 13:37 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
daoЕсли таки вы знаете как может транзакция "минимизации операций с диском" может поделитесь знаниями? )Видимо имелся в виду режим autocommit с соответствующим сбросом буфера журнала на диск после каждой инструкции. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2017, 14:06 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
invmdaoЕсли таки вы знаете как может транзакция "минимизации операций с диском" может поделитесь знаниями? )Видимо имелся в виду режим autocommit с соответствующим сбросом буфера журнала на диск после каждой инструкции. Режим автокоммита подразумевает неявный вызов commit'а после каждой операции изменения данных, если я правильно понимаю. Это равно явному открытию транзакции перед выполнением операции и после выполнения, то есть явному открытию транзакции на каждое изменение с явным подтверждением фиксации. Так что да, имел ввиду это. Ну а непосредственно в момент фиксации происходит запись на диск журналов. Описано здесь в секции Write-Ahead Transaction Log. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2017, 14:22 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
Ceib, уточню - т.е. у вас под авторexec PARSE_AND_SAVE_DATA @data_string; находится набор процедур которые парсят @data_string в разные таблицы ? или таки там парсится одна строка? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2017, 14:38 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
daoCeib, уточню - т.е. у вас под авторexec PARSE_AND_SAVE_DATA @data_string; находится набор процедур которые парсят @data_string в разные таблицы ? или таки там парсится одна строка? и вставляется в одну строку одной таблицы? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2017, 14:38 |
|
||
|
uncommittable transaction
|
|||
|---|---|---|---|
|
#18+
daodaoCeib, уточню - т.е. у вас под пропущено... находится набор процедур которые парсят @data_string в разные таблицы ? или таки там парсится одна строка? и вставляется в одну строку одной таблицы? @data_string это строка из одной таблицы, она парсится и, в зависимости от того, что получилось, сохраняется в одну строку одной из других таблиц. Процесс повторяется для всех @data_string. Примерно так: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.12.2017, 14:50 |
|
||
|
|

start [/forum/topic.php?fid=46&msg=39576333&tid=1690599]: |
0ms |
get settings: |
8ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
55ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
65ms |
get tp. blocked users: |
1ms |
| others: | 213ms |
| total: | 373ms |

| 0 / 0 |
