sql >> Database teknologi >  >> RDS >> Sqlserver

Sådan fungerer implicitte transaktioner i SQL Server

Der er fire transaktionstilstande i SQL Server. En af disse er implicit tilstand.

I SQL Server er en implicit transaktion, når en ny transaktion implicit startes, når den foregående transaktion er fuldført, men hver transaktion er eksplicit afsluttet med en COMMIT eller ROLLBACK erklæring.

Dette skal ikke forveksles med autocommit-tilstand, hvor transaktionen startes og afsluttes implicit.

De fire transaktionstilstande

SQL Server kan fungere i følgende transaktionstilstande:

Transaktionstilstand Beskrivelse
Autocommit transaktion Hvert individuelt udsagn er en transaktion.
Implicit transaktion En ny transaktion startes implicit, når den foregående transaktion er fuldført, men hver transaktion afsluttes eksplicit, typisk med en COMMIT eller ROLLBACK sætning afhængigt af DBMS.
Eksplicit transaktion Begyndte eksplicit med en linje såsom START TRANSACTION , BEGIN TRANSACTION eller lignende, afhængigt af DBMS, og eksplicit forpligtet eller rullet tilbage med de relevante udsagn.
Batch-omfattet transaktion Gælder kun for flere aktive resultatsæt (MARS). En eksplicit eller implicit transaktion, der starter under en MARS-session, bliver en batch-omfattet transaktion.

Implicit tilstand vs Autocommit

I SQL Server starter visse udsagn en transaktion automatisk, når de kører. Det er, som om de blev indledt af en usynlig BEGIN TRANSACTION erklæring.

I de fleste tilfælde er disse transaktioner også implicit begået, som om der var en usynlig COMMIT TRANSACTION udmelding. Sådanne transaktioner siges at være i autocommit-tilstand .

I andre tilfælde er der ingen usynlig COMMIT TRANSACTION for at matche den usynlige BEGIN TRANSACTION udmelding. Transaktionen forbliver i gang, indtil du eksplicit forpligter den eller ruller den tilbage med en COMMIT TRANSACTION eller ROLLBACK TRANSACTION udmelding. I dette tilfælde siges transaktionen at være i implicit tilstand .

Om transaktionen kører i implicit tilstand eller autocommit-tilstand afhænger af din IMPLICIT_TRANSACTIONS indstilling.

Erklæringer, der starter en implicit transaktion

Følgende sætninger starter en implicit transaktion i SQL Server.

  • ALTER TABLE
  • BEGIN TRANSACTION
  • CREATE
  • DELETE
  • DROP
  • FETCH
  • GRANT
  • INSERT
  • OPEN
  • REVOKE
  • SELECT (undtagen dem, der ikke vælger fra en tabel, såsom SELECT GETDATE() eller SELECT 1*1 )
  • TRUNCATE TABLE
  • UPDATE

Hver gang du kører disse T-SQL-sætninger, starter du en transaktion. Det meste af tiden vil transaktionen blive automatisk forpligtet. Så du startede og afsluttede transaktionen uden at skulle gøre det eksplicit.

Men afhængigt af din IMPLICIT_TRANSACTIONS indstilling, skal du muligvis udføre transaktionen eksplicit.

Når IMPLICIT_TRANSACTIONS er OFF

Når din IMPLICIT_TRANSACTIONS indstillingen er OFF , udfører ovenstående udsagn transaktioner i autocommit-tilstand. Det vil sige, de starter og afslutte transaktionen implicit.

Så det er som at have en usynlig BEGIN TRANSACTION erklæring og en usynlig COMMIT TRANSACTION erklæring, alt sammen fra den ene erklæring.

I dette tilfælde behøver du ikke at gøre noget for at forpligte eller tilbageføre transaktionen. Det var allerede gjort for dig.

Når IMPLICIT_TRANSACTIONS er ON

Når din IMPLICIT_TRANSACTIONS indstillingen er ON , opfører ovenstående udsagn sig lidt anderledes.

Når IMPLICIT_TRANSACTIONS indstillingen er ON , får ovenstående udsagn en usynlig BEGIN TRANSACTION erklæring, men de får ikke en tilsvarende COMMIT TRANSACTION erklæring.

Det betyder, at du eksplicit skal forpligte eller rulle tilbage transaktionen selv.

Men når transaktionstilstanden er implicit, er der ingen usynlig BEGIN TRANSACTION udstedes, hvis en transaktion allerede er i gang.

Eksempel

Her er et eksempel for at demonstrere 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 dette tilfælde indstiller jeg IMPLICIT_TRANSACTIONS til OFF og kør SELECT udmelding. Dette betød, at SELECT sætningen kørte i autocommit-tilstand, og derfor blev transaktionen startet og afsluttet implicit.

@@TRANCOUNT returnerede 0 , hvilket betyder, at der ikke kørte nogen transaktioner på det tidspunkt.

Her er den igen, bortset fra at denne gang indstiller vi IMPLICIT_TRANSACTIONS til 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 sidste @@TRANCOUNT returnerer værdien 1 . Det betyder, at vores transaktion stadig er i gang.

@@TRANCOUNT returnerer antallet af BEGIN TRANSACTION udsagn, der er opstået på den aktuelle forbindelse. Vi udstedte ikke eksplicit en, men en blev udstedt implicit.

Så vi er faktisk nødt til at foretage denne transaktion (eller rulle den tilbage) for at formindske @@TRANCOUNT ned til 0 .

COMMIT TRANSACTION;
SELECT @@TRANCOUNT AS TransactionCount;

Resultat:

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

Så koden for vores implicitte transaktion burde have inkluderet COMMIT erklæring:

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

Hvis du opdager, at implicitte transaktioner aktiveres uventet, kan det være på grund af ANSI_DEFAULTS indstilling.


  1. Forskel mellem GiST og GIN indeks

  2. Hvordan CHAR() virker i MariaDB

  3. E-mail-forespørgselsresultater som en HTML-tabel i SQL Server (T-SQL)

  4. Hvordan får man medarbejderne med deres ledere