資料庫並行控制是決定高併發下效能與一致性的核心。SQL Server (鎖基礎 + 行版本存放於 TempDB) 與 Oracle (純 MVCC,Undo Tablespace 存前映像) 代表兩大主流架構流派。本文深度剖析兩者在讀寫衝突、一致性語義、鎖升級、版本存儲管理、應用層影響等維度的本質差異。
| 維度 | SQL Server (預設 READ COMMITTED) | Oracle (READ COMMITTED / SERIALIZABLE) |
|---|---|---|
| 核心機制 | 鎖 + 可選行版本 (RCSI/SI) | 多版本並行控制 (MVCC) |
| 讀取者是否阻塞寫入者 | 預設 是 (共享鎖 S 阻塞排他鎖 X) | 否 (讀取 Undo 中的前映像) |
| 寫入者是否阻塞讀取者 | 預設 是 (X 鎖阻塞 S 鎖) | 否 (讀取提交前的舊版本) |
| 讀取一致性層級 | 語句級 (預設) / 交易級 (SNAPSHOT/Serializable) | 語句級 (RC) / 交易級 (Serializable) |
| 版本存儲位置 | TempDB (版本存放區) | Undo Tablespace / Rollback Segments |
| 版本清理機制 | Ghost Cleanup / Version Store 清理執行緒 | Undo 保留時間 (UNDO_RETENTION) 自動覆寫 |
-- 會話 1:開始修改,未提交
BEGIN TRAN;
UPDATE titles SET price = price * 1.05 WHERE title_id = 'BU2075';
-- 未 COMMIT/ROLLBACK
-- 會話 2:查詢同一資料表
SELECT title_id, title, price FROM titles ORDER BY title_id;
-- 結果:卡住等待,直到會話 1 提交或回滾
原因:會話 1 持有 X 鎖,會話 2 請求 S 鎖,相互阻塞。
繞過方案:SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 或 WITH (NOLOCK),但會讀到「髒資料」(未提交資料),不保證一致性。
-- 會話 1:修改薪資,未提交
UPDATE hr.employees SET salary = salary * 1.05 WHERE department_id = 20;
-- 會話 2:查詢同一資料
SELECT first_name, last_name, salary FROM hr.employees WHERE department_id = 20;
-- 結果:立即返回修改前的薪資 (一致性快照)
-- 會話 1 COMMIT 後,會話 2 重新查詢才會看到新薪資
原因:Oracle 將修改前的資料版本寫入 Undo Tablespace,查詢自動讀取舊版本,不需等待鎖釋放。
READ_COMMITTED_SNAPSHOT ON (RCSI) 或 ALLOW_SNAPSHOT_ISOLATION ON (SI) 後,寫入者在 TempDB 維護資料列版本。3967。UNDO_RETENTION 目標保留秒數,引擎自動擴展/縮減 Undo Tablespace。LOCK_ESCALATION = TABLE/AUTO/DISABLE (2008+) 控制。| 場景 | SQL Server 建議 | Oracle 建議 |
|---|---|---|
| 高併發 OLTP | 啟用 RCSI (資料庫級) 讓讀不阻寫,寫不阻讀;縮短交易範圍 | 預設 RC 已滿足大多數;長查詢注意 UNDO_RETENTION |
| 報表/分析查詢 | 專用報表實例 (Always On 可讀次要) 或 SNAPSHOT 隔離 | 預設 RC 即可,不阻塞 OLTP |
| 資料一致性要求極高 | SERIALIZABLE / SNAPSHOT (SI) + 衝突重試邏輯 | SERIALIZABLE (需應用處理 ORA-08177) |
| 批次大量更新 | 分批次、避免鎖升級至表級、考慮 TABLOCK 提示 | 分批次、COMMIT 頻率平衡 Undo 產生 |
SQL Server 以鎖為主、版本為輔,預設行為保守 (讀寫互斥),啟用 RCSI/SI 後可達類 Oracle 體驗,但版本存放於 TempDB 需容量規劃。Oracle 以純 MVCC 為核心,讀寫天然不阻塞,一致性由 Undo 保證,DBA 需管理 Undo 保留策略。無絕對優劣,唯有適配業務模式的架構選擇。 現代雲資料庫 (Azure SQL / Amazon RDS / Oracle Autonomous) 均在引擎層內建智能化並行控制,開發者更應聚焦於交易設計、隔離級別選擇、長查詢治理而非底層機制爭論。