Вопрос по transactions, sql-server – SQL Server переносит Select… Insert Queries в неявную транзакцию?

3

Когда я выполняю запрос выбора / вставки, SQL Server автоматически создает неявную транзакцию и, таким образом, обрабатывает ее как одну атомарную операцию?

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

INSERT INTO Table1 (FieldA)
SELECT 'newvalue' 
WHERE NOT EXISTS (Select * FROM Table1 where FieldA='newvalue')

Есть ли возможность "нового значения"? вставляется в таблицу другим пользователем между оценкой предложения WHERE и выполнением предложения INSERT, если оно явно не включено в транзакцию?

Является ли (или не делает) FieldA ключевым полем с уникальным свойством? Похоже, это хороший способ избежать дубликатов, что похоже на то, что вы ищете. JonnyBoats
Показательным признаком того, что операция выбора / вставки, вероятно, является атомарной, является то, что точка останова включает весь оператор. samis
Не могу вдаваться в подробности, но по сложным причинам я не могу напрямую добавлять ограничения в БД (отсюда мой обходной путь с этим типом запроса). JohnFx
Хорошо ... Просто, чтобы я не выглядел слишком умным здесь. Я дам немного фона. БД контролируется / принадлежит стороннему продукту, который я запрашиваю через их API, который строит фактический SQL, который выполняется. У него нет поддержки транзакций, и изменение объектов, которые может быть использована в их базе данных, может привести к аннулированию гарантии. знак равно JohnFx
Autocommit mode является режимом управления транзакциями по умолчанию для SQL Server Database Engine. Каждый оператор Transact-SQL фиксируется или откатывается после его завершения. Если оператор завершается успешно, он фиксируется; если он обнаруживает какую-либо ошибку, он откатывается. Соединение с экземпляром компонента Database Engine работает в режиме автоматической фиксации, если этот режим по умолчанию не был переопределен явными или неявными транзакциями. Режим автоматической фиксации также является режимом по умолчанию для ADO, OLE DB, ODBC и DB-Library. samis

Ваш Ответ

4   ответа
3

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

да - уровень изоляции отделен от транзакций, поэтому будет таким же, если вы не измените его с помощью подсказок или явной установки.
Я предполагаю, что в этой ситуации используется значение по умолчанию (READ COMMITTED), поскольку при этом используется неявная, а не явная транзакция. Это звучит правильно? JohnFx
0

SSMS 2016можно проверить, чтоSelect/Insert оператор запрашивает блокировку (и, скорее всего, работает атомарно):

Open a new query/connection for the following transaction and set a break-point on ROLLBACK TRANSACTION before starting the debugger:

BEGIN TRANSACTION     
INSERT INTO Table1 (FieldA) VALUES ('newvalue');    
ROLLBACK TRANSACTION --[break-point]

While at the above break-point, execute the following from a separate query window to show any locks (may take a few seconds to register any output):

SELECT * FROM sys.dm_tran_locks
 WHERE resource_database_id = DB_ID()
   AND resource_associated_entity_id = OBJECT_ID(N'dbo.Table1');

There should be a single lock associated to the BEGIN TRANSACTION/INSERT above (since by default runs in an ISOLATION LEVEL of READ COMMITTED)

OBJECT      **  **********  *   IX  LOCK    GRANT   1   

From another instance of SSMS, open up a new query and run the following (while still stopped at the above break-point):

INSERT INTO Table1 (FieldA)
SELECT 'newvalue'
WHERE NOT EXISTS (Select * FROM Table1 where FieldA='newvalue') 

This should hang with the string "(Executing)..." being displayed in the tab title of the query ,window (since @@LOCK_TIMEOUT is -1 by default).

Re-run the query from Step 2.

Another lock corresponding to the Select/Insert should now show:

OBJECT      **  **********  0   IX  LOCK    GRANT   1
OBJECT      **  **********  0   IX  LOCK    GRANT   1

ref: Как проверить, какие замки удерживаются на столе

dbcc opentran а также@@TRANCOUNT может также быть некоторой помощью.
4

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

Не так много. Я понимаю разницу. Причина, по которой я упомянул транзакции, в основном потому, что это ключевой механизм, используемый в SQL-сервере для обозначения критических секций / блокировок. В любом случае спасибо за ваш ответ. JohnFx
Транзакции и блокировки похожи на печенье и молоко -"Transactions работает наREAD UNCOMMITTED уровень не выдаютshared locks чтобы другие транзакции не могли изменить данные, прочитанные текущей транзакцией. Транзакции READ UNCOMMITTED также не блокируются эксклюзивными блокировками, которые не позволяют текущей транзакции читать строки, которые были изменены, но не зафиксированы другими транзакциями. & Quot;
"You will never ever have your data in an intermittent state when the operations are transacted." - Если грязное чтение разрешено уровнем изоляцииREAD UNCOMMITTEDзатем измененная запись, которая откатывается, может вернуться в БД, если впоследствии будет записана каким-либо процессом, который выполнял «грязное» чтение, что технически было бы прерывистым состоянием.

Похожие вопросы