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åsomSELECT GETDATE()
ellerSELECT 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.