Каков эффект от слишком длинной открытой транзакции в MSSQL?


11

Мне просто интересно, что произойдет, если вы начнете транзакцию в БД и забудете ее зафиксировать или откатить. Будет ли сервер не работает? Допустим, вы оставили его на 3 дня.

Есть также пользователи, которые используют его, предполагая, что другие пользователи не знали, что существует незакрытая транзакция (давайте просто предположим, что пользователи просто вставляют данные в базу данных). Каковы последствия этого действия?

Ответы:


14

Наличие открытой транзакции само по себе почти не будет иметь последствий. Простой

BEGIN TRANSACTION
-- wait for a while, doing nothing
-- wait a bit longer
COMMIT

в худшем случае будет содержать несколько байтов значений состояния. Ничего страшного.

Большинство программ будут выполнять реальную работу в рамках транзакции, и это другой вопрос. Смысл транзакции заключается в том, что вы можете быть уверены, что несколько фактов в базе данных верны одновременно, несмотря на то, что другие пользователи одновременно пишут в одну и ту же базу данных.

Возьмите канонический пример перевода денег между банковскими счетами. Система должна гарантировать, что исходный счет существует, имеет достаточные средства, целевой счет существует, и что дебет и кредит происходят или не происходят. Это должно гарантировать это, когда происходят другие транзакции, возможно, даже между этими двумя учетными записями. Система обеспечивает это, блокируя соответствующие таблицы. То, какие блокировки приняты, и сколько работы других людей вы видите, контролируется уровнем изоляции транзакций .

Поэтому, если вы выполняете большую работу, есть большая вероятность, что другие транзакции будут поставлены в очередь в ожидании объектов, на которых вы держите блокировки. Это уменьшит общую пропускную способность системы. В конце концов они достигнут пределов времени ожидания и потерпят неудачу, что является проблемой для общего поведения системы. Если вы используете оптимистический уровень изоляции, ваша транзакция может потерпеть неудачу, когда вы пытаетесь выполнить коммит из-за работы других.

Удержание замков забирает системные ресурсы. Это память, которую система не может использовать для обработки других запросов, что снижает пропускную способность.

Если была проделана большая работа, система может выбрать повышение блокировки . Вместо блокировки отдельных строк вся таблица будет заблокирована. Тогда будет затронуто больше одновременно работающих пользователей, пропускная способность системы будет снижаться, а влияние приложения будет выше.

Изменения данных записываются в файл журнала, как и блокировки, которые их защищают. Они не могут быть удалены из журнала до фиксации транзакции. Следовательно, очень длинная транзакция может вызвать переполнение файла журнала и связанные с ним проблемы.

Если текущая работа использует базу данных tempdb, что, вероятно, для больших рабочих нагрузок, ресурсы могут быть связаны до конца транзакции. В крайних случаях это может привести к сбою других задач, потому что для них больше нет места. У меня были случаи, когда плохо закодированная UPDATE заполняла базу данных tempdb, поэтому для сортировки отчета оставалось недостаточно диска, и отчет не удался.

Если вы выберете ОТКРЫТЬ транзакцию, или система выйдет из строя и восстановится, время, необходимое для того, чтобы система снова стала доступной, будет зависеть от того, сколько работы было выполнено. Простая открытая транзакция не повлияет на время восстановления, а на объем выполненной работы. Если транзакция была открыта, но простояла час, восстановление будет практически мгновенным. Если он писал постоянно в течение этого часа, эмпирическое правило таково, что время восстановления также будет около часа.

Как видите, длительные транзакции могут быть проблематичными. Для систем OLTP рекомендуется использовать одну транзакцию базы данных на одну бизнес-транзакцию. Для пакетного ввода процесса работы в блоках, с частыми коммитами и перезапуском логической кодировки Обычно несколько тысяч записей могут быть обработаны в одной транзакции БД, но это следует проверить на предмет параллелизма и потребления ресурсов.

Не поддавайтесь искушению перейти в другую крайность и полностью избегать транзакций и блокировок. Если вам необходимо поддерживать согласованность ваших данных (и зачем вам использовать базу данных?), Уровни изоляции и транзакции служат очень важной цели. Узнайте о своих возможностях и решите, с каким балансом параллелизма и правильности вы готовы жить для каждой части вашего приложения.


даже если он открыт три дня?
JanLeeYu

Да хоть на три дня. Важным моментом является объем работы, выполненной в то время, когда TX открыт, а не только то, как долго он был открыт. Конечно, как администратор БД, вы можете спросить владельца транзакции, почему он так долго должен ее открывать. Когда я управлял командой DBA, я регистрировал все TX, которые были открыты более 30 минут и разговаривали с владельцем.
Майкл Грин

OK. Спасибо за отличное объяснение. Хотя все тоже отлично справились.
JanLeeYu

Какое облегчение ... Еще раз спасибо за ответ.
JanLeeYu

"Плохо закодированное ОБНОВЛЕНИЕ" Да. Видел это. Оператор обновления внутри цикла, который не квалифицирует некоторые имена и приводит к поведению, аналогичному 1 = 1, поэтому он обновляет всю таблицу для каждой итерации цикла (что также помещает неверные данные в большинство этих строк).
jpmc26

6

Ваше самое большое последствие будет блокирование объектов, используемых в транзакции. Особенно, если вы предполагаете, что ваши пользователи вставляют данные, тогда эта длительная транзакция может включать инструкции SELECT для часто используемых таблиц. Заявления об обновлениях ваших пользователей могут быть не в состоянии получить необходимую блокировку, необходимую для завершения их обновлений или вставок.

Вторичная вещь, которая может произойти, - это активность файла журнала, скажем, если вы обновляли большой набор данных, часть журнала, которую использует транзакция, остается активной в течение этой транзакции. Вы не сможете повторно использовать эту часть журнала, пока транзакция не будет зафиксирована или откатана. В ситуациях, когда вы можете работать в сильно активной OLTP-системе, это может привести к быстрому росту вашего файла журнала и заполнению вашего устройства хранения.


например, тот, кто создал транзакцию, отключен от сервера, сможет ли он снова войти на сервер, чтобы закрыть транзакцию?
JanLeeYu

Это будет зависеть от того, была ли транзакция в среде, которая использовала MSDTC, это может быть потерянная транзакция. В этом случае, пользователь больше не сможет закрыть его сам ... Администратор БД должен был вмешаться, чтобы справиться с этим. Помимо этого, вы обычно должны видеть, как транзакция отменяется SQL Server, когда он отключается ... но опять же для больших транзакций, которые могут не иметь место каждый раз.

В случае, если администратор все еще сможет закрыть транзакцию правильно?
JanLeeYu

Я не могу ответить на этот вопрос, все зависит. У меня были случаи, когда сервер должен был быть перезапущен, или экземпляр перенесен на вторичный узел / реплику.

4

Незавершенная транзакция может содержать большое количество блокировок и вызывать блокировку

Если транзакция не завершена либо из-за истечения времени ожидания запроса, либо из-за того, что пакет был отменен в середине транзакции без выполнения оператора COMMIT или ROLLBACK для завершения транзакции, транзакция остается открытой, и все блокировки, полученные во время этой транзакции, продолжаются. быть проведенным. Последующие транзакции, выполненные в том же соединении, рассматриваются как вложенные транзакции, поэтому все блокировки, полученные в этих завершенных транзакциях, не снимаются. Эта проблема повторяется со всеми транзакциями, выполняемыми из одного и того же соединения, пока не будет выполнен ROLLBACK. В результате удерживается большое количество блокировок, пользователи блокируются, а транзакции теряются, что приводит к тому, что данные отличаются от ожидаемых.

источник


например, тот, кто создал транзакцию, отключен от сервера, сможет ли он снова войти на сервер, чтобы закрыть транзакцию?
JanLeeYu

Как только SQL Server узнает, что соединение потеряно, он откатит транзакцию. Смотрите здесь dba.stackexchange.com/questions/47404/… . Если один и тот же пользователь повторно подключится, это будет другой сеанс, поэтому он не сможет каким-либо образом «принять» старую транзакцию.
Майкл Грин
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.