Что произойдет, если вы не зафиксируете транзакцию в базе данных (скажем, SQL Server)?

108

Предположим, у меня есть запрос:

begin tran
-- some other sql code

А потом я забываю зафиксировать или откатиться.

Что произойдет, если другой клиент попытается выполнить запрос?

Charbel
источник

Ответы:

148

Пока вы не выполняете COMMIT или ROLLBACK транзакцию, она все еще "выполняется" и, возможно, удерживает блокировки.

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

marc_s
источник
1
ммм, хорошо, я понял, это создавало какую-то блокировку. Я не был уверен, что закрытие соединения действительно выведет меня из этого состояния. проблема заключалась в том, что я получал сообщение об ошибке при попытке зафиксировать. сейчас я закрыл соединение и все заработало.
Charbel
12
Боковое примечание: при использовании Management Studio закрытие окна запроса приведет к закрытию соединения
Джо Филлипс,
3
@BradleyDotNET: да, определенно
marc_s
2
Имейте в виду, что SQL Server Management Studio автоматически фиксируется, если вы закрываете окно запроса / соединение по умолчанию.
Нуно
1
Обратите внимание, что, когда клиент закрывает соединение, пока транзакция активна, это не всегда откат - это зависит от клиента и базы данных. Например, когда приложение Java закрывает соединение с базой данных Oracle, любые открытые соединения автоматически фиксируются.
AviD
38

Вы можете попробовать это сами, это должно помочь вам понять, как это работает.

Откройте два окна (вкладки) в студии управления, каждое из которых будет иметь собственное подключение к sql.

Теперь вы можете начать транзакцию в одном окне, сделать что-то вроде вставки / обновления / удаления, но еще не зафиксировать. затем в другом окне вы можете увидеть, как база данных выглядит вне транзакции. В зависимости от уровня изоляции таблица может быть заблокирована до тех пор, пока не будет зафиксировано первое окно, или вы можете (не) увидеть, что уже сделала другая транзакция и т. Д.

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

Также посмотрите, что происходит, когда вы выдаете ошибку в транзакции.

Очень важно понимать, как все это работает, иначе вы будете много раз озадачены тем, что делает sql.

Радоваться, веселиться! GJ.

Gjvdkamp
источник
хорошо, но будет ли транзакция записана в журнал, по крайней мере, до выполнения фиксации? Например, скажем, я хочу начать транзакцию, запустить команду вставки и «сделать что-нибудь еще», прежде чем я выполню фиксацию. будет ли моя команда вставки записана в журнал? таким образом, если сервер выйдет из строя перед выполнением фиксации ... он может вернуться туда, где он был, и я могу просто выполнить фиксацию позже (когда я закончу делать «что-то еще»).
user1870400
16

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

Следовательно, если вы начнете, а затем не зафиксируете, произойдет откат при закрытии соединения (поскольку транзакция была прервана без пометки как завершенной).

Писквор вышел из здания
источник
Так и должно быть, но так бывает не всегда.
FalcoGer
... например, MyISAM из mySQL, который , конечно, не поддерживает транзакции.
Писквор покинул здание
3

зависит от уровня изоляции входящей транзакции.

Объяснение изоляции транзакций sql

Xhalent
источник
6
Поведение транзакций не зависит от уровня изоляции. Количество блокировок, которые они могут вызвать, имеет значение.
marc_s
Я почти уверен, что то, какие данные могут быть прочитаны соединением, определенно зависит от уровня изоляции. Если у вас установлена ​​изоляция на READ UNCOMMITTED, вы можете читать данные, которые еще не зафиксированы, и на самом деле может быть откат в какой-то момент дорожки, но это гарантирует отсутствие блокировки. Если у вас установлен уровень изоляции READ COMMITTED, вы не можете читать незафиксированные строки - второй клиент зависнет, если вы не используете SNAPSHOT.
Xhalent 04
2

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

красный клевер
источник
1

Пример транзакции

начать транссексуал

Ваши операторы sql

если произошла ошибка откатить tran tt иначе зафиксировать tran tt

Пока вы не выполнили фиксацию транзакции, данные не будут изменены.

пользователь3386471
источник
1
Обратите внимание, что именование транзакций не только не нужно в MS SQL, но и может дать ложное ощущение контроля. BEGIN TRAN X ... BEGIN TRAN Y ... ROLLBACK Yне работает, например. См stackoverflow.com/questions/1273376/...
0

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

Вы можете использовать dbcc opentranдля просмотра сведений о самой старой открытой транзакции.

Мартин Смит
источник
0

Любая незавершенная транзакция оставит сервер заблокированным, и другие запросы не будут выполняться на сервере. Вам нужно либо откатить транзакцию, либо зафиксировать ее. Закрытие SSMS также приведет к прекращению транзакции, что позволит выполнять другие запросы.

Джош Мавриш
источник
-4

Поведение не определено, поэтому вы должны явно установить фиксацию или откат:

http://docs.oracle.com/cd/B10500_01/java.920/a96654/basic.htm#1003303

«Если режим автоматической фиксации отключен, и вы закрываете соединение без явной фиксации или отката ваших последних изменений, то выполняется неявная операция COMMIT».

Hsqldb делает откат

con.setAutoCommit(false);
stmt.executeUpdate("insert into USER values ('" +  insertedUserId + "','Anton','Alaf')");
con.close();

результат

2011-11-14 14: 20: 22,519 основная ИНФОРМАЦИЯ [SqlAutoCommitExample: 55] [AutoCommit enabled = false] 2011-11-14 14: 20: 22,546 основная ИНФОРМАЦИЯ [SqlAutoCommitExample: 65] [Найдено 0 # пользователей в базе данных]

Бернд Шац
источник
2
Это может быть верно для Oracle (я понятия не имею), но спрашивающий спрашивает о MS-SQL
PaulG
Первая цитата относится к драйверу JDBC, а не к серверу.
djechlin