MySQL在INSERT IGNORE未新增记录时避免AUTO_INCREMENT自增

在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的状况下这个模式能够达到最好的性能
相关文章
相关标签/搜索