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

Come funzionano le transazioni implicite in SQL Server

Esistono quattro modalità di transazione in SQL Server. Uno di questi è la modalità implicita.

In SQL Server, una transazione implicita è quando una nuova transazione viene avviata implicitamente al completamento della transazione precedente, ma ogni transazione viene completata in modo esplicito con un COMMIT o ROLLBACK dichiarazione.

Questo non deve essere confuso con la modalità autocommit, in cui la transazione viene avviata e terminata in modo implicito.

Le quattro modalità di transazione

SQL Server può funzionare nelle seguenti modalità di transazione:

Modalità transazione Descrizione
Autocommit transazione Ogni singolo estratto conto è una transazione.
Transazione implicita Una nuova transazione viene avviata implicitamente al completamento della transazione precedente, ma ogni transazione viene completata in modo esplicito, in genere con un COMMIT o ROLLBACK istruzione a seconda del DBMS.
Transazione esplicita Iniziato esplicitamente con una riga come START TRANSACTION , BEGIN TRANSACTION o simili, a seconda del DBMS, e esplicitamente impegnati o annullati con le dichiarazioni pertinenti.
Transazione con ambito batch Applicabile solo a più set di risultati attivi (MARS). Una transazione esplicita o implicita che inizia in una sessione MARS diventa una transazione con ambito batch.

Modalità implicita vs Autocommit

In SQL Server, alcune istruzioni avviano automaticamente una transazione quando vengono eseguite. È come se fossero preceduti da un invisibile BEGIN TRANSACTION dichiarazione.

Nella maggior parte dei casi, queste transazioni sono anche impegnate in modo implicito, come se ci fosse una COMMIT TRANSACTION invisibile dichiarazione. Si dice che tali transazioni siano in modalità di commit automatico .

Negli altri casi, non c'è COMMIT TRANSACTION invisibile per abbinare l'invisibile BEGIN TRANSACTION dichiarazione. La transazione rimane in corso fino a quando non la commetti in modo esplicito o la annulli con un COMMIT TRANSACTION o ROLLBACK TRANSACTION dichiarazione. In questo caso, si dice che la transazione è in modalità implicita .

Se la transazione viene eseguita in modalità implicita o in modalità autocommit dipende dal tuo IMPLICIT_TRANSACTIONS impostazione.

Dichiarazioni che avviano una transazione implicita

Le istruzioni seguenti avviano una transazione implicita in SQL Server.

  • ALTER TABLE
  • BEGIN TRANSACTION
  • CREATE
  • DELETE
  • DROP
  • FETCH
  • GRANT
  • INSERT
  • OPEN
  • REVOKE
  • SELECT (tranne quelli che non selezionano da una tabella, come SELECT GETDATE() o SELECT 1*1 )
  • TRUNCATE TABLE
  • UPDATE

Ogni volta che esegui queste istruzioni T-SQL, stai avviando una transazione. La maggior parte delle volte la transazione verrà automaticamente impegnata. Quindi hai iniziato e terminato la transazione senza doverlo fare esplicitamente.

Tuttavia, a seconda del tuo IMPLICIT_TRANSACTIONS impostazione, potrebbe essere necessario confermare la transazione in modo esplicito.

Quando IMPLICIT_TRANSACTIONS è OFF

Quando il tuo IMPLICIT_TRANSACTIONS l'impostazione è OFF , le istruzioni di cui sopra eseguono transazioni in modalità autocommit. Cioè, iniziano e terminare la transazione in modo implicito.

Quindi è come avere un BEGIN TRANSACTION invisibile istruzione e un invisibile COMMIT TRANSACTION dichiarazione, tutto da un'unica dichiarazione.

In questo caso, non è necessario eseguire alcuna operazione per eseguire il commit o il rollback della transazione. Per te è già stato fatto.

Quando IMPLICIT_TRANSACTIONS è ON

Quando il tuo IMPLICIT_TRANSACTIONS l'impostazione è ON , le affermazioni di cui sopra si comportano in modo leggermente diverso.

Quando IMPLICIT_TRANSACTIONS l'impostazione è ON , le istruzioni di cui sopra ottengono un BEGIN TRANSACTION invisibile ma non ottengono una COMMIT TRANSACTION corrispondente dichiarazione.

Ciò significa che è necessario eseguire personalmente il commit o il rollback della transazione.

Tuttavia, quando la modalità di transazione è implicita, nessun BEGIN TRANSACTION invisibile viene emesso se una transazione è già in corso.

Esempio

Ecco un esempio per dimostrare il concetto.

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

Risultato:

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

In questo caso, ho impostato IMPLICIT_TRANSACTIONS su OFF ed esegui SELECT dichiarazione. Ciò significava che il SELECT l'istruzione è stata eseguita in modalità autocommit e, pertanto, la transazione è stata avviata e terminata in modo implicito.

@@TRANCOUNT restituito 0 , il che significa che non c'erano transazioni in esecuzione in quel momento.

Eccolo di nuovo, tranne che questa volta impostiamo IMPLICIT_TRANSACTIONS su ON .

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

Risultato:

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

L'ultimo @@TRANCOUNT restituisce un valore di 1 . Ciò significa che la nostra transazione è ancora in corso.

@@TRANCOUNT restituisce il numero di BEGIN TRANSACTION dichiarazioni che si sono verificate sulla connessione corrente. Non ne abbiamo emesso uno esplicitamente, ma uno è stato emesso implicitamente.

Quindi abbiamo effettivamente bisogno di eseguire questa transazione (o annullarla) per decrementare il @@TRANCOUNT fino a 0 .

COMMIT TRANSACTION;
SELECT @@TRANCOUNT AS TransactionCount;

Risultato:

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

Quindi il codice per la nostra transazione implicita avrebbe dovuto includere COMMIT dichiarazione:

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

Risultato:

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

Se scopri che le transazioni implicite sono abilitate in modo imprevisto, potrebbe essere a causa di ANSI_DEFAULTS collocamento.