為了瞭解 MySQL Lock 使用時機 ,我幻想了一個訂票系統 | Piece of DevOps
每個 Database 最讓人好奇,但也最難一下子理解的,就是其中使用到的鎖(Lock)。在瞭解 MySQL 的鎖時,發現在 InnoDB 儲存引擎下(MySQL 預設使用),我們可以在 SELECT 查詢指令中,加入特定的關鍵字,來決定我們要使用什麼鎖來鎖定搜尋過的資料。關鍵字分別為: LOCK IN SHARE MODE FOR UPDATE 這兩種關鍵字分別代表兩種鎖,前者是代表 Shared Lock ,後者則是 Exclusive Lock 。在看過一些文章及官方文件後,大概明白為什麼可以在 SELECT 中,加上這兩把其中一把鎖的原因。原因就在於 InnoDB 在實作 Isolation Level 的 Repeatable Read 時,是以 Snapshot 的方式進行也就是 Multiversion concurrency control(MVCC)模式。此模式是在 Transaction 中,執行第一次的 SELECT 後,開始紀錄資料當下 Snapshot 版本,接下來只要在同 Transaction 內再次執行相同的 SELECT,透過指定當時的 Snapshot 版本,就可以獲得與第一次執行 SELECT 時的相同資料,進而達到 Repeatable Read 的效果。 在上述的情況下,雖然可以保持在同一個 Transaction 內看見的資料是一致的,但卻沒辦法保證資料不被修改,更無法察覺資料是否被修改(因為只會到看 Snapshot 的結果)。沒辦法保證資料不被修改跟無法察覺,會很糟嗎?為了要讓這兩件事感覺起來很糟,所以我幻想了一個訂票系統,以下的例子會讓你知道,可能可以糟到哪去。 三人購票一人免費的活動 慢速鐵路公司推出一個促銷活動。憑三張車票,就可以換一張免費車票。先不討論有誰會想搭慢速鐵路這個根本的問題。麻煩的一致性問題,就是那麼樸實無華。 車票使用的表(tickets) 用來紀錄現有的車票。因應接下來的劇情,加入三張票在表中。 tickets # CREATE CREATE TABLE tickets ( id INT NOT NULL AUTO_INCREMENT, train_no INT DEFAULT 0, car...