獨立測試通過不代表生產就緒。數十用戶並發修改同一訂單時,若未理解 Oracle 並發機制,將面臨更新丟失、資料不一致、效能雪崩、無法擴展四大災難。本文從 Oracle 獨特的鎖架構、多版本並發控制(MVCC)切入,並對比 DB2 根本差異,建立正確的並發設計思維。
INSERT/UPDATE/DELETE 針對受影響行加排他鎖(TX,模式 6)這是 Oracle 最獨特、最被誤解的特性:
SELECT ... FOR UPDATE)「讀不阻塞寫,寫不阻塞讀」—— 這是 Oracle 高並發的基石,也是與 SQL Server、DB2、MySQL(預設 RR 隔離級別)根本不同之處。
enq: TX - row lock contention經典案例:餘額檢查後扣款
-- Session A -- Session B
SELECT balance FROM accounts SELECT balance FROM accounts
WHERE id=1; -- 返回 100 WHERE id=1; -- 返回 100
-- 業務邏輯判斷 100 >= 50 -- 業務邏輯判斷 100 >= 80
UPDATE accounts SET balance=50 UPDATE accounts SET balance=20
WHERE id=1; WHERE id=1;
COMMIT; COMMIT;
-- 最終餘額 20,實際扣款 130!
兩個事務讀到相同的舊版本,各自基於舊版本計算新值,導致 更新丟失。Oracle 不會自動阻止這種情況。
SELECT ... FOR UPDATE 讀取時加鎖,序列化存取VERSION 或 CHECKSUM 欄位,UPDATE ... SET bal=bal-50, ver=ver+1 WHERE id=1 AND ver=old_ver,檢查回傳行數UPDATE accounts SET balance=balance-50 WHERE id=1 AND balance>=50,利用陳述式級一致性| 維度 | Oracle | DB2 |
|---|---|---|
| 鎖架構 | 意圖鎖 + 行級鎖標誌位(ITL),無鎖管理器 | 意圖鎖 + 鎖列表,每個鎖佔用 Locklist 記憶體(X:64B, S:32B) |
| 鎖升級 | 不存在 | 行鎖超過 LOCKLIST * MAXLOCKS 觸發升級為表鎖 |
| 純讀 SELECT | 零鎖,構建 CR 映像 | 依隔離級別加鎖:RR=S, RS=IS, CS=IS, UR=無鎖 |
| 一致性模型 | 陳述式級讀一致性(Statement-Level Read Consistency) | 交易級讀一致性(Transaction-Level,RR/RS/CS) |
| 讀寫並發 | 讀完全不阻塞寫 | 讀鎖(S/IS)阻塞寫鎖(X/IX),除非 UR 級別讀未提交 |
| 版本儲存 | UNDO 表空間(自動管理) | 日誌緩衝區 + 表空間,版本清理由鎖驅動 |
FOR UPDATE 或樂觀鎖SELECT 看到的是「查詢開始時刻」的已提交資料快照SELECT ... FOR UPDATE [NOWAIT|WAIT n|SKIP LOCKED]UNDO_RETENTION 設定掌握 Oracle 並發本質,不是為了炫技,而是為了寫出在生產環境真正可靠、可擴展的程式碼。記住:Oracle 給你自由,也給你責任。