Подтвердить что ты не робот

Что делает транзакция вокруг одного оператора?

Я понимаю, как транзакция может быть полезной для координирования пары обновлений. То, что я не понимаю, - это обматывание отдельных операторов транзакциями, что составляет 90% от того, что я когда-либо видел. Фактически, в реальном жизненном коде в моем опыте более часто встречается серия логически связанных транзакций, каждая из которых завернута в их собственную транзакцию, но целое не завернуто в транзакцию.

В MS-SQL есть ли какие-либо выгоды от упаковки отдельных выборок, одиночных обновлений, одиночных вставок или одиночных удалений в транзакции?

Я подозреваю, что это суеверное программирование.

4b9b3361

Ответ 1

Он ничего не делает. Все отдельные SQL-выражения (за редким исключением, такие как Bulk Inserts with No Log или Truncate Table) являются автоматическими "В транзакции", явно ли вы это говорите или нет. (Даже если они вставляют, обновляют или удаляют миллионы строк),

EDIT: на основе комментария @Phillip ниже... В текущих версиях SQL Server, даже Bulk Inserts и Truncate Table записывают некоторые данные в журнал транзакций, хотя и не так сильно, как другие операции. Критическое отличие от транзакционной перспективы состоит в том, что в этих других типах операций данные в ваших таблицах базы данных, которые изменяются, не находятся в журнале в состоянии, которое позволяет ему откатываться.

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

Единственная функция, которую предоставляют команды "Начать транзакцию", "Зафиксировать транзакцию" и "Сбросить транзакцию", - это позволить вам поместить два или более отдельных оператора SQL в одну транзакцию.

EDIT: (чтобы усилить комментарий комментариев...) ДА, это можно отнести к "суеверному" программированию, или это может быть признаком фундаментального непонимания характера транзакций базы данных. Более благотворительная интерпретация заключается в том, что это просто результат чрезмерного применения непротиворечивости, который является неуместным и еще одним примером эвфемизма Эмерсонов, который:

Глупое согласование - это хобгоблин маленьких умов,
обожаемый маленькими государственными деятелями, философами и богословами.

Ответ 2

Как сказал Чарльз Бретана, "он ничего не делает" - ничего кроме того, что уже сделано.

Вы когда-нибудь слышали о требованиях "ACID" реляционной базы данных? То, что "А" означает "Атомный", означает, что либо оператор работает полностью, либо не работает, - и, хотя оператор выполняется, нет, другие запросы могут выполняться на затронутых данных по этому запросу. BEGIN TRANSACTION/COMMIT "расширяет" эту функцию блокировки для работы, выполняемой несколькими операторами, но ничего не добавляет к отдельным операторам.

Тем не менее, журнал транзакций базы данных всегда, записанный при изменении базы данных (вставка, обновление, удаление). Это не вариант, который, как правило, раздражает людей. Да, там wierdness с объемными вставками и режимами восстановления, но он все равно записывается.

Здесь также будут выделены уровни изоляции. Суета с этим будет влиять на отдельные команды, но при этом все равно не будет делать запрос с объявленной транзакцией без какого-либо "автономного" запроса. (Обратите внимание, что они могут быть очень мощными и очень опасными для транзакций с несколькими заявками.) Также обратите внимание, что "nolock" не применяется к вставкам/обновлениям/удалениям - эти действия всегда требовали блокировок.

Ответ 3

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

например.

--------------------------------------------------------------
CREATE TABLE T1(CPK INT IDENTITY(1,1) NOT NULL, Col1 int, Col2 char(3));
INSERT INTO T1 VALUES (101, 'abc');
INSERT INTO T1 VALUES (101, 'abc');
INSERT INTO T1 VALUES (101, 'abc');
INSERT INTO T1 VALUES (101, 'abc');
INSERT INTO T1 VALUES (101, 'abc');
INSERT INTO T1 VALUES (101, 'abc');
INSERT INTO T1 VALUES (101, 'abc');

SELECT * FROM T1


--------------------------------------------------------------
/* MISTAKE SCENARIO     (run each row individually) */
--------------------------------------------------------------
BEGIN TRAN YOUR_TRANS_NAME_1;   /* open a trans named YOUR_TRANS_NAME_1 */
    UPDATE T1 SET COL2 = NULL;  /* run some update statement */
    SELECT * FROM T1;       /* OOPS ... forgot the where clause */
ROLLBACK TRAN YOUR_TRANS_NAME_1;    /* since it did bad things, roll it back */
    SELECT * FROM T1;       /* tans rolled back, data restored. */



--------------------------------------------------------------
/* NO MISTAKES SCENARIO (run each row individually) */
--------------------------------------------------------------

BEGIN TRAN YOUR_TRANS_NAME_2;
    UPDATE T1 SET COL2 = 'CBA' WHERE CPK = 4;   /* run some update statement */
    SELECT * FROM T1;               /* did it correctly this time */

COMMIT TRAN YOUR_TRANS_NAME_2           /* commit (close) the trans */

--------------------------------------------------------------

DROP TABLE T1

--------------------------------------------------------------

Ответ 4

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

Это то, что вам может или не нужно.

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

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

Неявные транзакции совершаются или откатываются незамедлительно после завершения или неудачи оператора DML.

Ответ 5

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

Другое, что я могу придумать, это то, что некоторые API-интерфейсы позволяют отключить автообновление, а код написан на всякий случай, если кто-то это сделает.