在MySQL5.7中作INSERT IGNORE時發現, 即便INSERT未成功執行, 表的自增主鍵卻自動加1了, 在某些狀況下須要避免這種行爲. 須要修改的變量是 innodb_autoinc_lock_mode, 將其設爲0後, 在INSERT未成功執行時不會自增主鍵.mysql
innodb_autoinc_lock_mode在MySQL各版本的默認值sql
根據MySQL官方手冊的說明: 安全
There are three possible settings for the innodb_autoinc_lock_mode configuration parameter. The settings are 0, 1, or 2, for 「traditional」, 「consecutive」, or 「interleaved」 lock mode, respectively. As of MySQL 8.0, interleaved lock mode (innodb_autoinc_lock_mode=2) is the default setting. Prior to MySQL 8.0, consecutive lock mode is the default (innodb_autoinc_lock_mode=1). 併發
在MySQL8中, 默認值爲 2 (interleaved, 交錯), 在MySQL8之前, 準確地說在8以前, 5.1以後, 默認值爲 1 (consecutive, 連續), 在更早的版本是 0性能
innodb_autoinc_lock_mode的說明優化
這個值主要用於平衡性能與安全(主從的數據一致性), insert主要有如下類型orm
- simple insert 如insert into t(name) values('test')
- bulk insert 如load data | insert into ... select .... from ....
- mixed insert 如insert into t(id,name) values(1,'a'),(null,'b'),(5,'c');
innodb_autoinc_lock_mode = 0:three
- 與更高版本的MySQL向後兼容
- 在這一模式下,全部的insert語句都要在語句開始的時候獲得一個表級的auto_inc鎖,在語句結束的時候才釋放這把鎖,一個事務可能包涵有一個或多個語句
- 它能保證值分配的可預見性,與連續性,可重複性,這個也就保證了insert語句在複製到slave的時候還能生成和master那邊同樣的值(它保證了基於語句複製的安全)
- 因爲在這種模式下auto_inc鎖一直要保持到語句的結束,因此這個就影響到了併發的插入
innodb_autoinc_lock_mode = 1:事務
- 這一模式對simple insert作了優化,因爲simple insert一次性插入值的個數能夠當即肯定, 因此mysql能夠一次生成幾個連續的值用於這個insert語句, 總的來講這個對複製也是安全的(保證了基於語句複製的安全)
- 這一模式也是MySQL8.0以前的默認模式, 這個模式的好處是auto_inc鎖不要一直保持到語句的結束, 只要語句獲得了相應的值後就能夠提早釋放鎖
innodb_autoinc_lock_mode = 2:rem
- 因爲這個模式下已經沒有了auto_inc鎖, 因此這個模式下的性能是最好的, 可是它也有一個問題, 就是對於同一個語句來講它所獲得的auto_incremant值可能不是連續的
- 如今mysql已經推薦把二進制的格式設置成row, 因此在binlog_format不是statement的狀況下這個模式能夠達到最好的性能