解說SQL的Transaction與隔離層級

什麼是Transaction?

Transaction,大陸有人翻譯為交易或事務,但都同一個意思。

它是一個執行過程中的一個邏輯單位。比方說SELECT、INSERT、UPDATE,當中也可能包含多個行為,比方說查詢後更新。為了確保資料庫的交易在各種情況下都是維持正確性,交易有四個特性,也就是俗稱的ACID。

1. Atomicity 原子性

原子性主張交易必須要維持統一不變的狀況,交易必須是全數成功,不然就得是全部失敗。
舉例: 假設你是消費者,進行消費後在前台的交易系統有存入這筆交易,但是系統的交易後台卻沒有這筆交易,顯示更新這個功能只做了一半,交易的行為破壞了原子性

2. Consistency 一致性

一致性主張,交易前與交易後都必須要遵守完整性的規範,比方說店家前台的交易系統與系統後台必須要維持一致性,交易的結果不統一破壞了一致性

3. Isolation 隔離性

隔離性代表了交易不應該互相干擾,假設你看到的戶頭有1000元,而你在領800去吃飯時,剛好電費同時扣款導致你無法進行交易。不夠嚴謹的隔離性後續會產生許多問題,等一下會一一介紹。

4. Durability 永久性

永久性意味對於資料的寫入是永久的,即使系統故障也不會丟失資料。

這些規範看起來很合理,但未必適合每種商業場景,實際上還是要多多考慮實際上的商業場景在做出決定。就好比高可用性與系統效能永遠都是一個無法兼得的選項一樣。端看你要如何取捨。

三種SQL隔離性會產生的問題

設定了錯誤的隔離層級會造成許多系統上難維護的課題,特別是在多執行緒的場景,使用Trasaction特性要特別謹慎。常見的隔離性不正確會有以下問題:

1. Dirty Read 髒讀

指一筆交易在處理過程中讀取了另外一個交易”未提交”的數據。
舉例:
帳戶原有1000,
A會

  1. 對帳戶領500
  2. 對帳戶存500
    B會
  3. 讀取帳戶餘額。

在兩者同時處理的併發情況下可能發生: A1 > B >A2
也就是說帳戶其實錢並沒有減少,但在B的視角中,可能產生帳戶少了500元的結果。

2. Non-Repeatable 不可重複讀

指一個交易範圍內,多次查詢某個數據,卻得到不同的結果。
舉例:
呈上例,B初次讀取時得到了500,但過一下子讀取後又得到了1000。兩次結果不一致。

3. Phantom Read 幻讀

一個交易範圍內,多次查詢某個數據,卻得到不同的資料筆數。

四種隔離層級

1. Read Uncommitted:

這個隔離層級可以讀取尚未commit的資料,因為資料包含為commit的資料,所以可能會產生以上三種問題。
這種隔離層級可能產生:

  • 髒讀
  • 不可重複讀
  • 幻讀

2. Read Committed:

這個隔離層級只允許讀取其他 transaction commit 過的資料,可以解決髒讀的問題,
不過如果一個 transaction 的兩個 SELECT 語法間有另一個交易 commit 了新資料,
會造成第一次讀取與第二次讀取結果不一致的問題,也就是上面介紹過的不可重複讀。
這種隔離層級可能產生:

  • 不可重複讀
  • 幻讀

3. Repeatable Read

同一個 transaction 內,除非自己修改,否則多次 SELECT 的結果都會相同,解決了不可重複讀的問題。
這種隔離層級可能產生:

  • 幻讀

4. Serializable

在一開始提過,是一個用效能換取一致性的隔離層級,
讓所有 transaction 序列化執行,避免併發可能會造成的問題。
可解決問題但效能低落。

以上


解說SQL的Transaction與隔離層級
https://clark1945.github.io/2024/05/19/解說SQL的Transaction與隔離層級/
Author
Clark Liu
Posted on
May 19, 2024
Licensed under