Transactions and Error Handling in SQL Server
Miriam Antona
Software Engineer
Concurrency: two or more transactions that read/change shared data at the same time.
Isolate our transaction from other transactions
READ COMMITTED
(default)READ UNCOMMITTED
REPEATABLE READ
SERIALIZABLE
SNAPSHOT
SET TRANSACTION ISOLATION LEVEL
{READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE | SNAPSHOT}
SELECT CASE transaction_isolation_level
WHEN 0 THEN 'UNSPECIFIED'
WHEN 1 THEN 'READ UNCOMMITTED'
WHEN 2 THEN 'READ COMMITTED'
WHEN 3 THEN 'REPEATABLE READ '
WHEN 4 THEN 'SERIALIZABLE'
WHEN 5 THEN 'SNAPSHOT'
END AS transaction_isolation_level
FROM sys.dm_exec_sessions
WHERE session_id = @@SPID
| transaction_isolation_level |
|-----------------------------|
| READ COMMITTED |
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
Dirty reads | Non-repeatable reads | Phantom reads | |
---|---|---|---|
READ UNCOMMITTED | yes | yes | yes |
Original balance account 5 = $35,000
Transaction1
BEGIN TRAN
UPDATE accounts
SET current_balance = 30000
WHERE account_id = 5;
ROLLBACK TRAN;
Transaction2
...
...
...
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT current_balance
FROM accounts WHERE account_id = 5;
| current_balance |
|-----------------|
| 30000,00 |
Transaction1
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN TRAN
SELECT * FROM accounts WHERE account_id = 5;
| current_balance |
|-----------------|
| 35000,00 |
Transaction2
...
...
BEGIN TRAN
UPDATE accounts
SET current_balance = 30000 WHERE account_id = 5;
COMMIT TRAN
Transaction1
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN TRAN
SELECT * FROM accounts WHERE account_id = 5;
| current_balance |
|-----------------|
| 35000,00 |
SELECT * FROM accounts WHERE account_id = 5;
| current_balance |
|-----------------|
| 30000,00 |
Transaction2
...
...
BEGIN TRAN
UPDATE accounts
SET current_balance = 30000 WHERE account_id = 5;
COMMIT TRAN
Transaction1
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN TRAN
SELECT * FROM accounts
WHERE current_balance BETWEEN 45000 AND 50000
| account_number | ... | current_balance |
|----------------------|-----|-----------------|
| 55555555552020202020 | ... | 50000,00 |
Transaction2
...
...
BEGIN TRAN
INSERT INTO accounts
VALUES ('55555555553939393939', 1, 45000)
COMMIT TRAN
Transaction1
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN TRAN
SELECT * FROM accounts
WHERE current_balance BETWEEN 45000 AND 50000
| account_number | ... | current_balance |
|----------------------|-----|-----------------|
| 55555555552020202020 | ... | 50000,00 |
SELECT * FROM accounts
WHERE current_balance BETWEEN 45000 AND 50000
| account_number |...| current_balance |
|----------------------|---|-----------------|
| 55555555553939393939 |...| 45000,00 | Phantom!
| 55555555552020202020 |...| 50000,00 |
Transaction2
...
...
BEGIN TRAN
INSERT INTO accounts
VALUES ('55555555553939393939', 1, 45000)
COMMIT TRAN
Pros:
Cons:
When to use it?:
Transactions and Error Handling in SQL Server