sql >> Databáze >  >> RDS >> Sqlserver

Jak fungují implicitní transakce na serveru SQL Server

SQL Server má čtyři režimy transakcí. Jedním z nich je implicitní režim.

Na serveru SQL Server je implicitní transakce, když je nová transakce implicitně zahájena po dokončení předchozí transakce, ale každá transakce je explicitně dokončena s COMMIT nebo ROLLBACK prohlášení.

Nezaměňujte to s režimem automatického potvrzení, kde je transakce zahájena a ukončena implicitně.

Čtyři režimy transakcí

SQL Server může pracovat v následujících režimech transakcí:

Režim transakce Popis
Automatické potvrzení transakce Každý jednotlivý výpis je transakce.
Implicitní transakce Nová transakce je implicitně zahájena po dokončení předchozí transakce, ale každá transakce je dokončena explicitně, obvykle s COMMIT nebo ROLLBACK v závislosti na DBMS.
Explicitní transakce Explicitně začíná řádkem, jako je START TRANSACTION , BEGIN TRANSACTION nebo podobné, v závislosti na DBMS, a explicitně potvrzené nebo vrácené zpět s příslušnými prohlášeními.
Transakce v dávkovém rozsahu Platí pouze pro více aktivních sad výsledků (MARS). Explicitní nebo implicitní transakce, která začíná v rámci relace MARS, se stává transakcí s dávkovým rozsahem.

Implicitní režim versus Autocommit

Na serveru SQL Server určité příkazy zahájí transakci automaticky při svém spuštění. Je to, jako by jim předcházelo neviditelné BEGIN TRANSACTION prohlášení.

Ve většině případů jsou tyto transakce také implicitně potvrzeny, jako by existovala neviditelná COMMIT TRANSACTION prohlášení. Říká se, že takové transakce jsou v režimu automatického potvrzení .

V ostatních případech neexistuje žádná neviditelná funkce COMMIT TRANSACTION aby odpovídala neviditelnému BEGIN TRANSACTION prohlášení. Transakce bude probíhat, dokud ji výslovně nepotvrdíte nebo ji nevrátíte zpět pomocí příkazu COMMIT TRANSACTION nebo ROLLBACK TRANSACTION prohlášení. V tomto případě se říká, že transakce je v implicitním režimu .

Zda transakce proběhne v implicitním režimu nebo režimu automatického potvrzení závisí na vašem IMPLICIT_TRANSACTIONS nastavení.

Výpisy, které zahajují implicitní transakci

Následující příkazy zahájí implicitní transakci na serveru SQL.

  • ALTER TABLE
  • BEGIN TRANSACTION
  • CREATE
  • DELETE
  • DROP
  • FETCH
  • GRANT
  • INSERT
  • OPEN
  • REVOKE
  • SELECT (kromě těch, které nevybírají z tabulky, jako je SELECT GETDATE() nebo SELECT 1*1 )
  • TRUNCATE TABLE
  • UPDATE

Kdykoli spustíte tyto příkazy T-SQL, zahájíte transakci. Ve většině případů bude transakce automaticky potvrzena. Takže jste zahájili a ukončili transakci, aniž byste to museli výslovně udělat.

Nicméně v závislosti na vašich IMPLICIT_TRANSACTIONS nastavení, možná budete muset transakci potvrdit explicitně.

Když IMPLICIT_TRANSACTIONS je OFF

Když vaše IMPLICIT_TRANSACTIONS nastavení je OFF , výše uvedené příkazy provádějí transakce v režimu automatického potvrzení. To znamená, že začínají a implicitně ukončit transakci.

Je to jako s neviditelným BEGIN TRANSACTION příkaz a neviditelný COMMIT TRANSACTION výpis, vše z jednoho výpisu.

V tomto případě nemusíte pro potvrzení nebo vrácení transakce nic dělat. Už to pro vás bylo hotové.

Když IMPLICIT_TRANSACTIONS je ON

Když vaše IMPLICIT_TRANSACTIONS nastavení je ON , výše uvedená tvrzení se chovají mírně odlišně.

Když IMPLICIT_TRANSACTIONS nastavení je ON , výše uvedené příkazy dostanou neviditelný BEGIN TRANSACTION příkaz, ale nedostanou odpovídající COMMIT TRANSACTION prohlášení.

To znamená, že musíte transakci explicitně potvrdit nebo vrátit zpět.

Pokud je však režim transakce implicitní, žádná neviditelná BEGIN TRANSACTION je vydáno, pokud transakce již probíhá.

Příklad

Zde je příklad pro demonstraci konceptu.

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

Výsledek:

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

V tomto případě jsem nastavil IMPLICIT_TRANSACTIONS na OFF a spusťte SELECT prohlášení. To znamenalo, že SELECT příkaz běžel v režimu autocommit, a proto byla transakce zahájena a ukončena implicitně.

@@TRANCOUNT vrátil 0 , což znamená, že v tomto okamžiku neprobíhaly žádné transakce.

Tady je to znovu, ale tentokrát jsme nastavili IMPLICIT_TRANSACTIONS na ON .

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

Výsledek:

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

Poslední @@TRANCOUNT vrací hodnotu 1 . To znamená, že naše transakce stále probíhá.

@@TRANCOUNT vrátí číslo BEGIN TRANSACTION příkazy, které se vyskytly na aktuálním připojení. Nevydali jsme ho explicitně, ale jeden byl vydán implicitně.

Takže ve skutečnosti potřebujeme potvrdit tuto transakci (nebo ji vrátit zpět), abychom snížili @@TRANCOUNT až na 0 .

COMMIT TRANSACTION;
SELECT @@TRANCOUNT AS TransactionCount;

Výsledek:

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

Kód pro naši implicitní transakci by tedy měl obsahovat COMMIT prohlášení:

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

Výsledek:

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

Pokud zjistíte, že implicitní transakce jsou neočekávaně povoleny, může to být způsobeno ANSI_DEFAULTS nastavení.


  1. SET NULL:Zadejte řetězec, který se má vrátit, kdykoli se v SQLcl / SQL*Plus objeví hodnota Null

  2. Převeďte datum řetězce ISO-8601 na datový typ časového razítka Oracle

  3. SQL Server Hromadné vložení souboru CSV s nekonzistentními uvozovkami

  4. Případ použití pro sp_prepare / sp_prepexec