sql >> Databasteknik >  >> RDS >> Sqlserver

Hur implicita transaktioner fungerar i SQL Server

Det finns fyra transaktionslägen i SQL Server. En av dessa är implicit läge.

I SQL Server är en implicit transaktion när en ny transaktion implicit startas när den föregående transaktionen slutförs, men varje transaktion är explicit slutförd med en COMMIT eller ROLLBACK uttalande.

Detta ska inte förväxlas med autocommit-läge, där transaktionen startas och avslutas implicit.

De fyra transaktionslägena

SQL Server kan fungera i följande transaktionslägen:

Transaktionsläge Beskrivning
Autocommit transaktion Varje individuellt uttalande är en transaktion.
Implicit transaktion En ny transaktion startas implicit när den föregående transaktionen slutförs, men varje transaktion är explicit slutförd, vanligtvis med en COMMIT eller ROLLBACK uttalande beroende på DBMS.
Explicit transaktion Började explicit med en rad som START TRANSACTION , BEGIN TRANSACTION eller liknande, beroende på DBMS, och uttryckligen åtagit sig eller rullat tillbaka med relevanta uttalanden.
Batch-omfattad transaktion Gäller endast för flera aktiva resultatuppsättningar (MARS). En explicit eller implicit transaktion som startar under en MARS-session blir en batch-omfattad transaktion.

Implicit läge vs Autocommit

I SQL Server startar vissa satser en transaktion automatiskt när de körs. Det är som om de föregåtts av en osynlig BEGIN TRANSACTION uttalande.

I de flesta fall är dessa transaktioner också implicit utförda, som om det fanns en osynlig COMMIT TRANSACTION påstående. Sådana transaktioner sägs vara i autocommit-läge .

I andra fall finns det ingen osynlig COMMIT TRANSACTION för att matcha den osynliga BEGIN TRANSACTION påstående. Transaktionen förblir pågående tills du uttryckligen genomför den eller återställer den med en COMMIT TRANSACTION eller ROLLBACK TRANSACTION påstående. I det här fallet sägs transaktionen vara i implicit läge .

Huruvida transaktionen körs i implicit läge eller autocommit-läge beror på din IMPLICIT_TRANSACTIONS inställning.

Uttalanden som startar en implicit transaktion

Följande satser startar en implicit transaktion i SQL Server.

  • ALTER TABLE
  • BEGIN TRANSACTION
  • CREATE
  • DELETE
  • DROP
  • FETCH
  • GRANT
  • INSERT
  • OPEN
  • REVOKE
  • SELECT (förutom de som inte väljer från en tabell, till exempel SELECT GETDATE() eller SELECT 1*1 )
  • TRUNCATE TABLE
  • UPDATE

Varje gång du kör dessa T-SQL-satser startar du en transaktion. För det mesta kommer transaktionen att genomföras automatiskt. Så du startade och avslutade transaktionen utan att uttryckligen behöva göra det.

Men beroende på din IMPLICIT_TRANSACTIONS kan du behöva utföra transaktionen uttryckligen.

När IMPLICIT_TRANSACTIONS är OFF

När din IMPLICIT_TRANSACTIONS inställningen är OFF , utför ovanstående uttalanden transaktioner i autocommit-läge. Det vill säga, de startar och avsluta transaktionen implicit.

Så det är som att ha en osynlig BEGIN TRANSACTION uttalande och en osynlig COMMIT TRANSACTION påstående, allt från ett påstående.

I det här fallet behöver du inte göra något för att begå eller återställa transaktionen. Det var redan gjort för dig.

När IMPLICIT_TRANSACTIONS är ON

När din IMPLICIT_TRANSACTIONS inställningen är ON , ovanstående påståenden beter sig något annorlunda.

När IMPLICIT_TRANSACTIONS inställningen är ON , ovanstående påståenden får en osynlig BEGIN TRANSACTION men de får inte en motsvarande COMMIT TRANSACTION uttalande.

Detta innebär att du uttryckligen måste utföra eller återställa transaktionen själv.

Men när transaktionsläget är implicit, ingen osynlig BEGIN TRANSACTION utfärdas om en transaktion redan pågår.

Exempel

Här är ett exempel för att demonstrera konceptet.

SELECT @@TRANCOUNT AS TransactionCount;
SET IMPLICIT_TRANSACTIONS OFF;
SELECT TOP 1 ProductName, ProductPrice FROM Products;
SELECT @@TRANCOUNT AS TransactionCount;

Resultat:

+--------------------+
| TransactionCount   |
|--------------------|
| 0                  |
+--------------------+
(1 row affected)
Commands completed successfully.
+-------------------------+----------------+
| ProductName             | ProductPrice   |
|-------------------------+----------------|
| Left handed screwdriver | 25.99          |
+-------------------------+----------------+
(1 row affected)
+--------------------+
| TransactionCount   |
|--------------------|
| 0                  |
+--------------------+
(1 row affected)

I det här fallet ställer jag in IMPLICIT_TRANSACTIONS till OFF och kör SELECT påstående. Detta innebar att SELECT uttalandet körde i autocommit-läge, och därför startades och avslutades transaktionen implicit.

@@TRANCOUNT returnerade 0 , vilket betyder att det inte fanns några transaktioner som kördes vid den tidpunkten.

Här är det igen, förutom att den här gången ställer vi in ​​IMPLICIT_TRANSACTIONS till ON .

SELECT @@TRANCOUNT AS TransactionCount;
SET IMPLICIT_TRANSACTIONS ON;
SELECT TOP 1 ProductName, ProductPrice FROM Products;
SELECT @@TRANCOUNT AS TransactionCount;

Resultat:

+--------------------+
| TransactionCount   |
|--------------------|
| 0                  |
+--------------------+
(1 row affected)
Commands completed successfully.
+-------------------------+----------------+
| ProductName             | ProductPrice   |
|-------------------------+----------------|
| Left handed screwdriver | 25.99          |
+-------------------------+----------------+
(1 row affected)
+--------------------+
| TransactionCount   |
|--------------------|
| 1                  |
+--------------------+
(1 row affected)

Den sista @@TRANCOUNT returnerar värdet 1 . Det betyder att vår transaktion fortfarande pågår.

@@TRANCOUNT returnerar antalet BEGIN TRANSACTION uttalanden som har inträffat på den aktuella anslutningen. Vi utfärdade inte uttryckligen en, men en utfärdades implicit.

Så vi måste faktiskt utföra den här transaktionen (eller återställa den) för att minska @@TRANCOUNT ner till 0 .

COMMIT TRANSACTION;
SELECT @@TRANCOUNT AS TransactionCount;

Resultat:

+--------------------+
| TransactionCount   |
|--------------------|
| 0                  |
+--------------------+
(1 row affected)

Så koden för vår implicita transaktion borde ha inkluderat COMMIT uttalande:

SELECT @@TRANCOUNT AS TransactionCount;
SET IMPLICIT_TRANSACTIONS ON;
SELECT TOP 1 ProductName, ProductPrice FROM Products;
COMMIT TRANSACTION;
SELECT @@TRANCOUNT AS TransactionCount;

Resultat:

+--------------------+
| 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

Om du upptäcker att implicita transaktioner oväntat aktiveras kan det bero på ANSI_DEFAULTS miljö.


  1. Bästa datatypen för att lagra pengar i MySQL

  2. JDBC batch insert prestanda

  3. Tvinga InnoDB att kontrollera främmande nycklar på ett eller flera tabeller igen?

  4. Använda utdataparametrar för lagrad procedur i C#