複習資料庫的 Isolation Level 與圖解五個常見的 Race Conditions
Locks
Exclusive Lock (Write Lock, X-Lock)
Transaction 在拿到資料的 Exclusive Lock 後就可以對資料做寫入的動作,這個時候其他 Transaction 則不能讀取,也不能寫入資料。
如果一筆資料被加上了 Shared Lock 或是 Exclusive Lock,就無法再拿到這筆資料的 Exclusive Lock,如果想要對這筆資料做寫入,就必須排隊等待,一直到資料上所有的 Shared Locks 或 Exclusive Lock 都被釋出後,再重新搶 Exclusive Lock。
Shared Lock (Read Lock, S-Lock)
資料被加上 Shared Lock 時,就無法再被加上 Exclusive Lock,所以其他 Transaction 將無法對這筆資料做寫入,但是還是可以繼續讀取這筆資料。概念有點像是不准你寫入,但是為了效能,我繼續與你 Share 資料讓你讀取。
比較特別的是,同一筆資料可以『同時』被多個 Transactions 加上 Shared Locks,當一比資料上有一個或多個 Share Locks 時,就沒有任何 Transaction 可以拿到 Exclusive Lock,也就沒有人可以對資料做寫入,必須等到所有 Shared Locks 都被釋出後再搶 Exclusive Lock。
但是當資料上只有 1 個 Shared Lock,而且這個 Shared Lock 的擁有者是 Transaction 自己本身時,Transaction 就可以直接將這個 Shared Lock 『升級』,變成 Exclusive Lock,直接對資料做寫入。
Range Lock
對一個 range 內的資料做 Lock,主要用來避免 Phantom 現象。例如如果執行下面的 MySQL 指令:
SELECT * FROM student WHERE height >= 170 FOR UPDATE;
除了被讀取到的資料會被加上 Exclusive Lock 外,在 height 從 170 到無限大的 range 也會被加上 Exclusive Lock,任何 height 介於這個 Range Lock 範圍內的資料都不能讀取也不能寫入。
以 InnoDB 來說,如果 Isolation Level 設定為 Serializable 的時候,其他 Transaction 不能讀取也不能寫入 height 介於 Range Lock 內的資料。但是如果 Isolation Level 設定為 Repeatable Read 的時候,因為 InnoDB 在 RR Isolation 的實作是採用 Snapshot Isolation,讀取時都是讀取 Snapshot 內的資料,所以讀取…