Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Как работят имплицитните транзакции в SQL Server

Има четири режима на транзакции в 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 настройка.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Кога/Защо да използвам каскадиране в SQL Server?

  2. SQL Server UNION - Какво е поведението по подразбиране ORDER BY

  3. T-SQL Cast срещу Convert

  4. Как да определите стойността на полето, която не може да се преобразува в (десетична, float,int) в SQL Server

  5. Премахване на идентичност от колона в таблица