select...for update再insert造成deadlock的陷阱
最近side project在寫購票系統,因而踩中了這個坑。這個坑其實對InnoDB的鎖的觀念不熟悉的人會很難發現造成deadlock的原因,因此想特別寫一篇記錄一下,幫助也在開發類似功能的大家少走一點冤望路。
本篇的講解順序會先帶大家重現我之前引發Deadlock的購票功能邏輯,再來說明資料表使用InnoDB引擎下產生如此Deadlock的原因。
環境
- 本篇範例使用的DB是 MariaDB 10.3.7 (開源版的MySQL)
- 資料表採用預設的 InnoDB 引擎,隔離層級也是預設的 Repeatable Read
- 範例資料表
ticket
的schema如下:
CREATE TABLE `ticket` ( `id` int(11) NOT NULL AUTO_INCREMENT, `show_id` int(11) NOT NULL, `user_id` int(11) NOT NULL, PRIMARY KEY (`id`), KEY `ticket_show_id_IDX` (`show_id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4
id
是主鍵(PK)、show_id
為了之後查詢上的需要,有建非唯一索引(non-unique index)、user_id
理論上是外鍵(FK),但這個欄位不是本篇的重點所以忽略他。
近期迴響