前段時間某數據表運行過程中,出現自增字段突然跳躍式增長的問題,潛心研究發現,問題導致原因可能是因為並發寫入導致
於是通過各種途徑查閱是因為innodb_autoinc_lock_mode參數設置的不同表現所在,於是進行了調整,在此對該參數的理解記錄一二。
中文翻譯地址:https://blog.csdn.net/ashic/article/details/53810319
其文章中主要提及,mysql的3種插入方式以及innodb_autoinc_lock_mode的3種參數選擇相關內容
三種模式簡要說明
首先,該參數僅在InnoDB引擎下生效,myisam引擎下,無論什么樣自增id鎖都是表級鎖
0:traditonal (每次都會產生表鎖)
1:consecutive (mysql的默認模式,會產生一個輕量鎖,simple insert會獲得批量的鎖,保證連續插入)
2:interleaved (不會鎖表,來一個處理一個,並發最高)
如何理解,以及參數如何選擇?
1、innodb_autoinc_lock_mode為0時的,也就是官方說的traditional級別
該自增鎖是表鎖級別,且必須等待當前SQL執行完成后或者回滾掉才會釋放,這樣在高並發的情況下可想而知自增鎖競爭是比較大的
2、innodb_autoinc_lock_mode為1時的,也就是官方說的consecutive級別
這時如果是單一的insert SQL,可以立即獲得該鎖,並立即釋放,而不必等待當前SQL執行完成(除非在其他事務中已經有session獲取了自增鎖)。另外當SQL是一些批量insert sql時,比如insert into ...select ...,load data,replace ..select..時,這時還是表級鎖,可以理解成退化為必須等待當前SQL執行完才釋放。可以認為,該值為1時是相對比較輕量的鎖,也不會對復制產生影響,唯一的缺陷是產生的自增值不一定是完全連續的
3、innodb_autoinc_lock_mode為2時,也就是官方說的interleaved 級別
所有insert種類的SQL都可以立馬獲得鎖並釋放,這時的效率最高。但是會引入一個新的問題:當binlog_format為statement時,這時的復制沒法保證安全,因為批量的insert,比如insert ..select..語句在這個情況下,也可以立馬獲取到一大批的自增id值,不必鎖整個表,slave在回放這個sql時必然會產生錯亂
問題分析
在此我們看到mysql的默認模式是2,官方表示其是連續插入,但實際上在這一模式simple insert做了優化,由於simple insert一次性插入值的個數可以立馬得到確定,所以mysql可以一次生成幾個連續的值,用於這個insert語句,而只要語句得到了相應的值后就可以提前釋放鎖,這就導致插入是連續的,但如果插入的語句存在錯誤的話(本次的值已經被分配,下次會增加),實際上自增的字段可能不連續
也就是說該模式只保證插入的連續性,但自增字段的連續性無法保證,而我們遇到的問題恰恰是要保證自增字段的連續性。
於是綜合考慮之后我們啟用了0模式,觀察一段時間之后發現滿足我們的需求,保證了字段的連續性。
至此問題得到解決。
作者:舊舊的 <393210556@qq.com> 解決問題的方式,就是解決它一次