淺談InnoDB的next-key locking策略
InnoDB 儲存引擎預設隔離級別為可重複讀(Repeatable Read),該隔離級別下加行鎖採用的是next-key locking 策略。
1)記錄鎖(Record Locks):鎖定指定行的索引項
2)Gap Locks:鎖定某一個範圍內的索引,但不包括記錄本身
3)間隙鎖定(Next-Key Locks):鎖定一個範圍內的索引,並且鎖定記錄本身 Next-Key Locks = Record Locks + Gap Locks
A next-key lock is a combination of a record lock on the index record and a gap lock on the gap before the index record
InnoDB在預設配置下(隔離級別:可重複讀;innodb_locks_unsafe_for_binlog=OFF:採用gap locking),對於索引的查詢採用 next-key locks。這樣做避免了幻讀現象的產生。
By default, InnoDB operates in REPEATABLE READ transaction isolation level and with the innodb_locks_unsafe_for_binlog system variable disabled. In this case, InnoDB uses next-key locks for searches and index scans, which prevents phantom rows
特別的,
1、當鎖定的索引項含有唯一屬性的時候,Next-Key Lock 會進行優化,將其降級為Record Lock,即僅鎖住索引本身,不是範圍。
2、當唯一索引是由多個列組成,而query僅查詢多個列中的其中一個,則依然使用 Next-key lock。
3、通過主鍵或者唯一索引來鎖定不存在的值,則依然使用 Next-key lock。。
強制關閉Gap Lock,僅使用記錄鎖從而避免阻塞(有幻讀的風險):配置引數 innodb_locks_unsafe_for_binlog = 1 或者隔離級別設為 READ COMMITTED
By default, the value of innodb_locks_unsafe_for_binlog is 0 (disabled), which means that gap locking is enabled: InnoDB uses next-key locks for searches and index scans. To enable the variable, set it to 1. This causes gap locking to be disabled: InnoDB uses only index-record locks for searches and index scans.
The effects of enabling innodb_locks_unsafe_for_binlog are the same as setting the transaction isolation level toREAD COMMITTED
(1)採用next-key locks的InnoDB無法插入除了鎖定行外的其他行的測試案例:
http://www.cnblogs.com/zhoujinyi/p/3435982.html
(2)何登成 --- MySQL加鎖處理分析
http://hedengcheng.com/?p=771
(3)《深入淺出MySQL資料庫開發優化與管理維護》開發篇
(4)https://dev.mysql.com/doc/refman/5.5/en/innodb-locking.html
(5)https://dev.mysql.com/doc/refman/5.5/en/innodb-consistent-read.html