SQL Transaction is a set of SQL commands that performed as single component of work unit. All SQL commands within the transaction are committed if executed successfully, or rolled back if any of the SQL command fail. It is used to provide reliable way to allow correct recovery of failure and keep database consistent.
Here are the list of different transaction modes in SQL Server,
- Autocommit transaction
- Implicit transaction
- Explicit transaction
- Batch-scoped transaction
- Distributed transaction
By default, SQL Server operates in autocommit transaction mode. All T-SQL statement is treated as a transaction and automatically committed or rolled back upon its completion. This behavior is changed when an implicit transaction is enabled or start of an explicit transaction.
Implicit transaction is enabled with
SET IMPLICIT_TRANSACTIONS ON
statement. SQL Server automatically start an implicit transaction on the next T-SQL statement (e.g. update, insert, alter). While the transaction is started automatically, COMMIT
and ROLLBACK
statement is used explicitly to end the transaction. To disable implicit transaction, use SET IMPLICIT_TRANSACTIONS OFF
statement.Explicit transaction is started with
BEGIN TRANSACTION
statement. The transaction is committed with COMMIT TRANSACTION
or rolled back with ROLLBACK TRANSACTION
statement.Batch-scoped transaction only apply to MARS (Multiple Active Result Sets). Implicit or explicit transaction started in MARS is managed as batch-scoped transaction. This type of transaction is rolled back if the batch or stored procedure which started the transaction does not complete (commit/rollback) its transaction before the batch or stored procedure exits.
Distributed transaction is a type of transaction usually span over two or more servers. The transaction is managed by transaction manager such as Microsoft Distributed Transaction Coordinator (MS DTC). Transaction within single instance across multiple databases is considered as distributed transaction however managed locally and internally by the single instance. The distributed transaction is started with
BEGIN DISTRIBUTED TRANSACTION
statement. COMMIT TRANSACTION
and ROLLBACK TRANSACTION
are used to commit or rollback the distributed transaction. Local transaction is promoted to distributed transaction when SET REMOTE_PROC_TRANSACTIONS ON
and a remote query are executed.Distributed transaction is also known as two-phase commit (2PC). In the first phase, prepare phase, transaction manager (MS DTC or local server instance for single instance-multiple databases transaction) receive the transaction commit request, and sends prepare command to all resource manager (the participating servers) to make the transaction durable and flush its respective data and log to disk. In the second phase, commit phase, once the transaction manager receives successful prepare from all resource manager, it issues commit command to all resource manager to complete the commit. After transaction manager receives complete commit, it sends notification back to the original requester and remove (forget) the transaction from its list.
Here are some tests with transaction log to show how these different type of transaction modes start and commit. Test setup,
CREATE DATABASE TEST; GO ALTER DATABASE TEST SET RECOVERY SIMPLE; GO USE TEST; GO CREATE TABLE dbo.Table1 ( ID int IDENTITY(1,1) PRIMARY KEY CLUSTERED, detail varchar(10) ); GO
Autocommit transaction,
--Initial IAM, PFS Page Allocation and etc INSERT INTO dbo.Table1 VALUES ('test0'); --Clear the transaction log CHECKPOINT; INSERT INTO dbo.Table1 VALUES ('test1'); INSERT INTO dbo.Table1 VALUES ('test2'); DBCC LOG (TEST, 0);
The transaction log shows each insert statement is treated as a transaction. The first insert statement begin its transaction at line 5 and commit the transaction at line 7. Same with second insert transaction.
Implicit Transaction,
--Clear the table
TRUNCATE TABLE dbo.Table1; GO --Initial IAM, PFS Page Allocation and etc INSERT INTO dbo.Table1 VALUES ('test0'); --Clear the transaction log CHECKPOINT; SET IMPLICIT_TRANSACTIONS ON; INSERT INTO dbo.Table1 VALUES ('test1'); INSERT INTO dbo.Table1 VALUES ('test2'); COMMIT; SET IMPLICIT_TRANSACTIONS OFF; DBCC LOG (TEST, 0);
Due to implicit transaction mode is enabled, it begins a transaction on first insert transaction and only commit the transaction on the commit statement. Transaction log shows that both insert transactions are within the same transaction begin at line 5 and commit at line 8.
Explicit Transaction,
--Clear the table
TRUNCATE TABLE dbo.Table1; GO --Initial IAM, PFS Page Allocation and etc INSERT INTO dbo.Table1 VALUES ('test0'); --Clear the transaction log CHECKPOINT; BEGIN TRAN INSERT INTO dbo.Table1 VALUES ('test1'); INSERT INTO dbo.Table1 VALUES ('test2'); COMMIT TRAN; DBCC LOG (TEST, 0);
The
BEGIN TRAN
starts an explicit transaction and commit on the COMMIT TRAN
statement. The transaction start at line 5 and commit at line 8.Batch-Scoped Transaction,
--Clear the table
TRUNCATE TABLE dbo.Table1; GO --Initial IAM, PFS Page Allocation and etc INSERT INTO dbo.Table1 VALUES ('test0'); --Clear the transaction log CHECKPOINT;
In this example, PowerShell is used to open a MARS connection and executes insert statements with an explicit transaction without commit/rollback statement. After the query completed, the transaction is automatically rollback due to the fact that SQL Server is treating it as batch-scoped transaction.
$connection = New-Object System.Data.SqlClient.SqlConnection $connection.ConnectionString = 'server=TESTSERVER;database=TEST;Trusted_Connection=True;MultipleActiveResultSets=True;' $command = New-Object System.Data.SqlClient.SqlCommand $command.Connection = $connection $command.CommandText = "BEGIN TRAN " + "INSERT INTO TEST.dbo.Table1 VALUES ('test1'); " + "INSERT INTO TEST.dbo.Table1 VALUES ('test1'); " $connection.Open() $command.ExecuteNonQuery() $connection.Close()
The transaction log shows that the transactions are rolled back.
Distributed Transaction,
--Create another database CREATE DATABASE TEST1 GO ALTER DATABASE TEST1 SET RECOVERY SIMPLE; GO USE TEST1; GO CREATE TABLE dbo.RemoteTable1 ( ID int IDENTITY(1,1) PRIMARY KEY CLUSTERED, detail varchar(10) ); GO --Initial IAM, PFS Page Allocation and etc INSERT INTO dbo.RemoteTable1 VALUES ('test0'); CHECKPOINT; GO --Back to TEST database USE TEST; GO --Clear the table TRUNCATE TABLE dbo.Table1; GO --Initial IAM, PFS Page Allocation and etc INSERT INTO dbo.Table1 VALUES ('test0'); --Clear the transaction log CHECKPOINT; --Insert 2 transactions to table1 in TEST database, and 2 transactions to remotetable1 in TEST1 database BEGIN DISTRIBUTED TRAN INSERT INTO TEST.dbo.Table1 VALUES ('test1'); INSERT INTO TEST.dbo.Table1 VALUES ('test2'); INSERT INTO TEST1.dbo.RemoteTable1 VALUES ('test1'); INSERT INTO TEST1.dbo.RemoteTable1 VALUES ('test2'); COMMIT; DBCC LOG (TEST, 0); DBCC LOG (TEST1, 0);
The above test simulates distributed transaction across multiple databases in a single instance. From the log, the resource manager (server instance) first inserts the rows, when transaction manager (in this case, the same server instance as well) receive the commit command, it issues a prepare command (line 7) and then commit the transaction (line 9). Note that SQL Server will automatically promote this transaction as distributed transaction even with just a regular explicit transaction with
BEGIN TRAN
since the transaction involves multiple databases. As this is a local distributed transaction managed by the single instance, the transaction is removed (forget at line 10) after the successful commit.Note that
BEGIN TRANSACTION
and BEGIN TRAN
; COMMIT
, COMMIT TRAN
and COMMIT TRANSACTION
; ROLLBACK
, ROLLBACK TRAN
and ROLLBACK TRANSACTION
are interchangeable respectively in this post.
No comments:
Post a Comment