Има четири режима на транзакции в SQL Server. Един от тях е имплицитният режим.
В SQL Server неявна транзакция е, когато нова транзакция е неявно стартирана, когато предишната транзакция завърши, но всяка транзакция е изрично завършена с COMMIT
или ROLLBACK
изявление.
Това не трябва да се бърка с режима на автоматично извършване, при който транзакцията се стартира и приключва имплицитно.
Четирите режима на транзакции
SQL Server може да работи в следните режими на транзакции:
Режим на транзакция | Описание |
---|---|
Автоматично извършване на транзакция | Всяко отделно изявление е транзакция. |
Неявна транзакция | Нова транзакция се стартира имплицитно, когато предишната транзакция завърши, но всяка транзакция е изрично завършена, обикновено с COMMIT или ROLLBACK изявление в зависимост от СУБД. |
Изрична транзакция | Изрично започва с ред като START TRANSACTION , BEGIN TRANSACTION или подобен, в зависимост от СУБД, и изрично ангажирани или върнати обратно със съответните оператори. |
Транзакция с обхват на партида | Приложимо само за множество активни набори от резултати (MARS). Изрична или неявна транзакция, която започва под сесия на MARS, става транзакция с обхват на партида. |
Неявен режим срещу автоматично завършване
В SQL Server определени изрази стартират транзакция автоматично, когато се изпълняват. Сякаш са предшествани от невидима BEGIN TRANSACTION
изявление.
В повечето случаи тези транзакции също са имплицитно ангажирани, сякаш е имало невидима COMMIT TRANSACTION
изявление. Казва се, че такива транзакции са в режим на автоматично извършване .
В други случаи няма невидима COMMIT TRANSACTION
за да съвпадне с невидимия BEGIN TRANSACTION
изявление. Транзакцията остава в ход, докато не я извършите изрично или не я върнете обратно с COMMIT TRANSACTION
или ROLLBACK TRANSACTION
изявление. В този случай се казва, че транзакцията е в неявен режим .
Дали транзакцията се изпълнява в имплицитен режим или в режим на автоматично извършване зависи от вашите IMPLICIT_TRANSACTIONS
настройка.
Изявления, които започват неявна транзакция
Следните изрази стартират неявна транзакция в SQL Server.
ALTER TABLE
BEGIN TRANSACTION
CREATE
DELETE
DROP
FETCH
GRANT
INSERT
OPEN
REVOKE
SELECT
(с изключение на тези, които не избират от таблица, катоSELECT GETDATE()
илиSELECT 1*1
)TRUNCATE TABLE
UPDATE
Всеки път, когато изпълнявате тези T-SQL оператори, започвате транзакция. През повечето време транзакцията ще бъде автоматично ангажирана. Така че започнахте и прекратихте транзакцията, без да се налага да го правите изрично.
Въпреки това, в зависимост от вашите IMPLICIT_TRANSACTIONS
настройка, може да се наложи да извършите транзакцията изрично.
Когато IMPLICIT_TRANSACTIONS
е OFF
Когато вашият IMPLICIT_TRANSACTIONS
настройката е OFF
, горните оператори извършват транзакции в режим на автоматично извършване. Тоест започвати прекрати транзакцията имплицитно.
Така че е като да имате невидима BEGIN TRANSACTION
изявление и невидима COMMIT TRANSACTION
изявление, всичко от едно изявление.
В този случай не е необходимо да правите нищо, за да ангажирате или да отмените транзакцията. Вече беше направено за вас.
Когато IMPLICIT_TRANSACTIONS
е ON
Когато вашият IMPLICIT_TRANSACTIONS
настройката е ON
, горните твърдения се държат малко по-различно.
Когато IMPLICIT_TRANSACTIONS
настройката е ON
, горните изрази получават невидима BEGIN TRANSACTION
изявление, но те не получават съответен COMMIT TRANSACTION
изявление.
Това означава, че трябва изрично да ангажирате или отмените транзакцията сами.
Въпреки това, когато режимът на транзакция е имплицитен, няма невидима BEGIN TRANSACTION
се издава, ако транзакцията вече е в ход.
Пример
Ето пример за демонстриране на концепцията.
SELECT @@TRANCOUNT AS TransactionCount;
SET IMPLICIT_TRANSACTIONS OFF;
SELECT TOP 1 ProductName, ProductPrice FROM Products;
SELECT @@TRANCOUNT AS TransactionCount;
Резултат:
+--------------------+ | TransactionCount | |--------------------| | 0 | +--------------------+ (1 row affected) Commands completed successfully. +-------------------------+----------------+ | ProductName | ProductPrice | |-------------------------+----------------| | Left handed screwdriver | 25.99 | +-------------------------+----------------+ (1 row affected) +--------------------+ | TransactionCount | |--------------------| | 0 | +--------------------+ (1 row affected)
В този случай задавам IMPLICIT_TRANSACTIONS
до OFF
и стартирайте SELECT
изявление. Това означаваше, че SELECT
изявлението се изпълняваше в режим на автоматично извършване и следователно транзакцията беше стартирана и приключила имплицитно.
@@TRANCOUNT
върна 0
, което означава, че в този момент не са се изпълнявали транзакции.
Ето го отново, освен че този път зададохме IMPLICIT_TRANSACTIONS
до ON
.
SELECT @@TRANCOUNT AS TransactionCount;
SET IMPLICIT_TRANSACTIONS ON;
SELECT TOP 1 ProductName, ProductPrice FROM Products;
SELECT @@TRANCOUNT AS TransactionCount;
Резултат:
+--------------------+ | TransactionCount | |--------------------| | 0 | +--------------------+ (1 row affected) Commands completed successfully. +-------------------------+----------------+ | ProductName | ProductPrice | |-------------------------+----------------| | Left handed screwdriver | 25.99 | +-------------------------+----------------+ (1 row affected) +--------------------+ | TransactionCount | |--------------------| | 1 | +--------------------+ (1 row affected)
Последният @@TRANCOUNT
връща стойност от 1
. Това означава, че нашата транзакция все още е в ход.
@@TRANCOUNT
връща номера на BEGIN TRANSACTION
изявления, които са възникнали при текущата връзка. Не сме издали изрично такъв, но такъв беше издаден неявно.
Така че всъщност трябва да извършим тази транзакция (или да я върнем назад), за да намалим @@TRANCOUNT
до 0
.
COMMIT TRANSACTION;
SELECT @@TRANCOUNT AS TransactionCount;
Резултат:
+--------------------+ | TransactionCount | |--------------------| | 0 | +--------------------+ (1 row affected)
Така че кодът за нашата имплицитна транзакция трябваше да включва COMMIT
изявление:
SELECT @@TRANCOUNT AS TransactionCount;
SET IMPLICIT_TRANSACTIONS ON;
SELECT TOP 1 ProductName, ProductPrice FROM Products;
COMMIT TRANSACTION;
SELECT @@TRANCOUNT AS TransactionCount;
Резултат:
+--------------------+ | TransactionCount | |--------------------| | 0 | +--------------------+ (1 row affected) Commands completed successfully. +-------------------------+----------------+ | ProductName | ProductPrice | |-------------------------+----------------| | Left handed screwdriver | 25.99 | +-------------------------+----------------+ (1 row affected) Commands completed successfully. +--------------------+ | TransactionCount | |--------------------| | 0 | +--------------------+ (1 row affected)
ANSI_DEFAULTS
Ако установите, че имплицитните транзакции са активирани неочаквано, това може да се дължи на ANSI_DEFAULTS
настройка.