隔離級別 (Isolation Levels)

★★★★★Reviewed

FromDDIAHigh

📚 From the Books

隔離級別 (Isolation Levels)Transactions

隔離級別是一組「我願意容忍哪些並發異常」的契約。級別越高、異常越少,但並發度與吞吐越低。理解它要從會發生什麼壞事反推,而不是背名字。

🧠 Intuition

TIP

不要記「四個級別」,要記「四種異常」:髒讀、不可重複讀、幻讀、寫偏斜。每個級別只是「擋掉前 N 種」的開關。問題永遠是:我的業務不能忍受哪一種?

⚖️ Tradeoffs

Read Committed — 擋髒讀
  • 只讀已 commit 的值,寫加行鎖直到 commit。
  • 仍會發生不可重複讀與幻讀。
  • 多數資料庫的預設(如 PostgreSQL)。
Snapshot Isolation / Repeatable Read — 擋不可重複讀
  • 交易看到「開始那一刻」的一致快照,靠 MVCC 實作(讀不擋寫)。
  • 擋掉髒讀與不可重複讀;PostgreSQL 的 SI 連幻讀也擋掉,但仍會寫偏斜
  • 讀多寫少的 OLTP 甜蜜點:高並發又有一致快照。
Serializable — 擋全部,含寫偏斜
  • 效果等同交易一個個排隊執行。實作有三條路:
    • 實際序列化執行(單執行緒,如 VoltDB / Redis)。
    • 兩階段鎖 (2PL):讀寫都加鎖,正確但易卡、吞吐低。
    • SSI(可序列化快照隔離):MVCC + 偵測危險讀寫相依,衝突才 abort 重試——樂觀,高並發下勝出。

🔑 Takeaways

✍️ My Notes

2026-07-01

  • Q: Snapshot Isolation 既然連幻讀都能擋,為什麼還會寫偏斜?
  • A: 因為 SI 保證「讀到一致快照」,但兩個交易讀的是同一份舊快照、各自更新不同的列,彼此的寫互相看不到,於是合起來違反了「至少留一個值班醫師」這類跨列不變量。SI 只偵測「寫到同一列」的衝突,偵測不到「基於同一前提寫不同列」。要擋它得上 Serializable(SSI 會偵測這種讀寫相依)。

📖 Further Reading

🔗 Dive Deeper