CodeGym /課程 /SQL SELF /交易隔離等級入門

交易隔離等級入門

SQL SELF
等級 39, 課堂 4
開放

想像一下你在咖啡廳打工,一個服務生在廚房查蛋糕庫存,另一個則在幫新客人下蛋糕單。在理想世界裡,他們應該都看到一樣的蛋糕數量,這樣才不會出現像「重複預訂」這種烏龍。但現實世界裡,並行操作就可能出現各種問題啦。

這裡有三個最常見的麻煩:

  1. Dirty Read(髒讀): 一個查詢看到另一個查詢還沒 commit 的變更。如果這些變更被 rollback,第一個查詢就像剛去面試的大學生一樣天真。

  2. Non-Repeatable Read(不可重複讀): 一個查詢兩次讀同一筆資料,但中間有人改了它。就像你去車站看火車時刻表,過一分鐘回來發現車被取消了。或者你找錢時票被別人買走了 XD

  3. Phantom Read(幽靈讀): 一個查詢看到一部分資料,但兩次查詢間有人插入新資料,結果就變了。就像你公司標案沒中,結果除了你跟市長老婆的標案外其他都被取消了。

交易隔離等級

既然知道這些問題,來看看 PostgreSQL 給我們什麼工具來解決——交易隔離等級。這就像幫並行交易訂規矩。隔離等級越高,交易互相干擾的機會就越小。但這樣會犧牲「服務速度」,也就是效能啦。

PostgreSQL 的隔離等級

  1. Read Uncommitted(讀未提交資料):

    • 允許讀到還沒 commit 的變更(對,這就是髒讀的經典範例)。
    • 在 PostgreSQL 裡其實會被當成 Read Committed,所以純正的 Read Uncommitted 不支援。PostgreSQL 覺得這太不靠譜了,直接拒絕實作。
  2. Read Committed(讀已提交變更):

    • 避免髒讀。
    • 交易只能看到執行時已經 commit 的資料。
    • 但還是可能出現 Non-Repeatable Read 跟 Phantom Read。
  3. Repeatable Read(可重複讀):

    • 保證你讀到的資料,在這次交易期間都不會變。
    • 避免髒讀跟不可重複讀。
    • 但幽靈資料還是有可能出現。
  4. Serializable(可序列化):

    • 保證交易執行起來就像一個一個排隊來一樣。
    • 三種問題都能避免:髒讀、不可重複讀、幽靈資料。
    • 最嚴格——也是最慢——的隔離等級。

為什麼交易隔離很重要?

想像一個網路商店的資料庫,成千上萬的用戶同時下單。如果隔離等級沒設好,會出現一堆衝突:從「商品消失」到「訂單重複」都有可能。

選對隔離等級可以幫你搞定交易競爭,讓效能跟資料正確性取得平衡。舉例來說:

  • 分析系統通常選最低隔離等級(像 Read Committed),因為資料精確度沒那麼重要。
  • 金融系統就會選 Serializable,這樣才不會算錯錢或重複扣款。

隔離等級的應用範例

  1. Read Committed

這個等級保證你不會讀到可能被 rollback 的資料。

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN;

-- 讀取帳戶資料。
SELECT balance FROM accounts WHERE account_id = 1;

-- 如果有其他交易更新這個餘額,這裡會馬上看到新資料。
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;

COMMIT;
  1. Repeatable Read

這個等級保證你讀到的資料,在這次交易期間都不會變。

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN;

-- 讀取帳戶資料。
SELECT balance FROM accounts WHERE account_id = 1;

-- 就算有其他交易更新這個餘額,你也看不到變化。
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;

COMMIT;
  1. Serializable

這個等級下,交易就像系統裡只有你一個人在動作。

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN;

-- 讀取帳戶資料。
SELECT balance FROM accounts WHERE account_id = 1;

-- 任何其他想改這筆資料的交易都會被鎖住,直到你這筆結束。
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;

COMMIT;

怎麼選隔離等級?

選隔離等級要看你的需求:

  • 如果速度比精確重要,而且你能接受幽靈資料——選 Read Committed。
  • 如果精確重要,但還想保有高效能——用 Repeatable Read。
  • 如果你要 100% 資料正確,就算慢也沒關係——那就 Serializable。

小心喔!高隔離等級可能會造成鎖死,讓系統變慢。最聰明的做法就是在效能跟資料一致性間找到平衡點。

2
任務
SQL SELF, 等級 39, 課堂 4
上鎖
設定交易的隔離等級
設定交易的隔離等級
1
問卷/小測驗
交易入門,等級 39,課堂 4
未開放
交易入門
交易入門
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION