交易 (Transaction) 是資料庫並發控制的核心單位,遵循 ACID 特性 (原子性、一致性、隔離性、持久性)。SQL Server 透過鎖定、版本儲存、記錄機制實現交易隔離,保護資料完整性同時最大化並發度。
| 現象 | 說明 | 發生條件 |
|---|---|---|
| 髒讀 | 讀取到其他交易未提交的修改資料 | 讀取交易未取得共享鎖 (S Lock),或隔離等級為 READ UNCOMMITTED |
| 不可重複讀 | 同一交易多次讀取同一資料列,結果不一致 (被其他交易修改/刪除) | 讀取交易釋放共享鎖後,寫入交易取得排他鎖 (X Lock) 修改 |
| 幻讀 | 同一交易多次執行相同範圍查詢,回傳列數不同 (被其他交易插入/刪除) | 範圍查詢未鎖定間隙 (Gap),插入交易在間隙新增列 |
| 隔離等級 | 髒讀 | 不可重複讀 | 幻讀 | 實作機制 |
|---|---|---|---|---|
| READ UNCOMMITTED | ✅ 可能 | ✅ 可能 | ✅ 可能 | 不取得共享鎖,直接讀取資料頁 |
| READ COMMITTED (預設) | ❌ 防止 | ✅ 可能 | ✅ 可能 | 讀取時取得瞬間共享鎖,讀完即釋放 |
| REPEATABLE READ | ❌ 防止 | ❌ 防止 | ✅ 可能 | 讀取時取得共享鎖,持有至交易結束 |
| SNAPSHOT | ❌ 防止 | ❌ 防止 | ❌ 防止 | 資料列版本控制 (Row Versioning),讀取不阻塞寫入 |
| SERIALIZABLE | ❌ 防止 | ❌ 防止 | ❌ 防止 | 範圍鎖 (Key-Range Lock),完全序列化存取 |
-- 交易層級
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; -- 或 REPEATABLE READ, SNAPSHOT, SERIALIZABLE
BEGIN TRANSACTION;
-- 交易邏輯
COMMIT;
-- 查詢層級 (僅影響該陳述式)
SELECT * FROM dbo.Orders WITH (NOLOCK); -- 等同 READ UNCOMMITTED
SELECT * FROM dbo.Orders WITH (READCOMMITTED); -- 明確指定
SELECT * FROM dbo.Orders WITH (REPEATABLEREAD);
SELECT * FROM dbo.Orders WITH (SERIALIZABLE);
-- 允許資料庫使用快照隔離 (需獨佔存取)
ALTER DATABASE MyDB SET ALLOW_SNAPSHOT_ISOLATION ON;
-- 啟用預設 READ COMMITTED 使用快照 (RCSI)
ALTER DATABASE MyDB SET READ_COMMITTED_SNAPSHOT ON;
RCSI 讓預設 READ COMMITTED 行為改為讀取版本存儲,大幅減少讀寫封鎖,適合高並發 OLTP 系統。
| 既有鎖 \ 要求鎖 | S | U | X | IS | IX |
|---|---|---|---|---|---|
| S | ✅ | ✅ | ❌ | ✅ | ❌ |
| U | ✅ | ❌ | ❌ | ✅ | ❌ |
| X | ❌ | ❌ | ❌ | ❌ | ❌ |
| IS | ✅ | ✅ | ❌ | ✅ | ✅ |
| IX | ❌ | ❌ | ❌ | ✅ | ✅ |
-- 檢視目前鎖定
SELECT * FROM sys.dm_tran_locks;
-- 檢視正在等待的工作階段
SELECT * FROM sys.dm_os_waiting_tasks WHERE wait_type LIKE 'LCK%';
-- 活動監視器 / sp_who2 / sp_lock (舊版)
-- 擴展事件 (Extended Events) 捕獲 deadlock_graph
WAITFOR DELAY 釋放鎖SQL Server 2014+ 引入無鎖架構,使用樂觀並發控制 (OCC) 與多版本並發控制 (MVCC),完全避免傳統鎖定爭用,適合極高並發熱點資料。交易隔離等級支援 SNAPSHOT、REPEATABLE READ、SERIALIZABLE (語義不同)。