1. 程式人生 > >MySQL在INSERT IGNORE未新增記錄時避免AUTO_INCREMENT自增

MySQL在INSERT IGNORE未新增記錄時避免AUTO_INCREMENT自增

在MySQL5.7中做INSERT IGNORE時發現, 即使INSERT未成功執行, 表的自增主鍵卻自動加1了, 在某些情況下需要避免這種行為. 需要修改的變數是 innodb_autoinc_lock_mode, 將其設為0後, 在INSERT未成功執行時不會自增主鍵.

innodb_autoinc_lock_mode在MySQL各版本的預設值

根據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主要有以下型別

  • 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:

  • 與更高版本的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:

  • 由於這個模式下已經沒有了auto_inc鎖, 所以這個模式下的效能是最好的, 但是它也有一個問題, 就是對於同一個語句來說它所得到的auto_incremant值可能不是連續的
  • 現在mysql已經推薦把二進位制的格式設定成row, 所以在binlog_format不是statement的情況下這個模式可以達到最好的效能