交易是資料庫一致性的基石。本文系統梳理 SQL Server 交易的核心概念、四大 ACID 特性、隔離等級機制、常用控制語句,並針對死鎖、鎖升級等實務痛點提供應對策略。
交易是一組不可分割的邏輯工作單元,具有明確的開始與結束。SQL Server 中每條 DML 語句預設即為隱式交易;顯式交易則由 BEGIN TRANSACTION 開啟,以 COMMIT 提交或 ROLLBACK 回滾。
交易過程中所有操作均寫入交易日誌。檢查點機制定期掃描日誌:已完成交易寫入資料檔並標記提交;未完成交易不寫入資料檔,標記未提交。此機制保證崩潰恢復時的資料一致性。
| 特性 | 英文 | 核心含義 | 實現機制 |
|---|---|---|---|
| 原子性 | Atomicity | 全做或全不做,無中間態 | 日誌回滾 |
| 一致性 | Consistency | 交易前後資料庫完整性約束保持滿足 | 約束、觸發器、規則 |
| 隔離性 | Isolation | 並發交易互不干擾,不可讀取中間態 | 鎖、版本存儲、隔離等級 |
| 持久性 | Durability | 提交後永久生效,不怕斷電 | WAL(預寫日誌)、強制寫入 |
BEGIN TRANSACTION -- 開啟交易
COMMIT TRANSACTION -- 提交
ROLLBACK TRANSACTION -- 回滾
SAVE TRANSACTION savepoint -- 設定存檔點,支援部分回滾
@@TRANCOUNT -- 目前巢狀交易層級
XACT_STATE() -- 交易狀態:1=可提交, -1=不可提交(已標記回滾), 0=無交易
最佳實務: 在 TRY...CATCH 區塊中包裹交易,捕獲錯誤時檢查 XACT_STATE() 決定回滾或提交。
SQL Server 2012+ 提供 5 種隔離等級,由低到高並發性遞減、一致性遞增:
| 等級 | 別名 | 髒讀 | 不可重複讀 | 幻讀 | 鎖機制 | 適用場景 |
|---|---|---|---|---|---|---|
| READ UNCOMMITTED | 未授權讀取 | 允許 | 允許 | 允許 | 排他寫鎖 | 報表近似查詢、臨時分析 |
| READ COMMITTED | 授權讀取 | 禁止 | 允許 | 允許 | 瞬間共享讀鎖+排他寫鎖 | 預設等級、OLTP 核心業務 |
| REPEATABLE READ | 可重複讀取 | 禁止 | 禁止 | 允許 | 共享讀鎖(持有至結束)+排他寫鎖 | 需穩定統計值的報表 |
| SNAPSHOT | 快照隔離 | 禁止 | 禁止 | 禁止 | 版本存儲,讀不阻寫,寫不阻讀 | 高並發、長查詢、需語句級一致性 |
| SERIALIZABLE | 序列化 | 禁止 | 禁止 | 禁止 | 範圍鎖,完全序列化執行 | 極高一致性需求、金融結算 |
關鍵差異: SNAPSHOT 需資料庫層級啟用 ALLOW_SNAPSHOT_ISOLATION 與 READ_COMMITTED_SNAPSHOT,透過 tempdb 版本存儲實現「讀寫不阻塞」,但會增加 tempdb 壓力與寫入開銷。
SET DEADLOCK_PRIORITY、啟用追蹤旗標 1222 記錄死鎖圖。TABLOCK 提示主動加表鎖。-- 會話級
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; -- 或 SNAPSHOT, SERIALIZABLE 等
-- 語句級提示
SELECT * FROM Orders WITH (READUNCOMMITTED); -- 等同 NOLOCK
SELECT * FROM Orders WITH (READCOMMITTEDLOCK); -- 強制加共享鎖
SELECT * FROM Orders WITH (UPDLOCK, HOLDLOCK); -- 模擬 REPEATABLE READ
正確選擇隔離等級,是在並發效能與資料一致性間找到業務可接受的平衡點。建議:核心 OLTP 採用 READ COMMITTED + 行版本控制;報表查詢採用 SNAPSHOT 或 READ UNCOMMITTED;極少數金融結算採用 SERIALIZABLE。