MySQL的自增主键是连续自增吗?( 三 )

你一定有两个疑问:为什么默认设置下,insert … select 要使用语句级的锁?为什么这个参数的默认值不是 2?原因就是为了保证数据的一致性 。
在生产上,尤其是有 insert … select 这种批量插入数据的场景时,从并发插入数据性能的角度考虑,我建议你这样设置:innodb_autoinc_lock_mode=2  , 并且 binlog_format=row. 这样做,既能提升并发性,又不会出现数据一致性问题 。
需要注意的是,我这里说的批量插入数据,包含的语句类型是 insert … select、replace … select 和 load data 语句 。
但是 , 在普通的 insert 语句里面包含多个 value 值的情况下,即使 innodb_autoinc_lock_mode 设置为 1,也不会等语句执行完成才释放锁 。因为这类语句在申请自增 id 的时候 , 是可以精确计算出需要多少个 id 的,然后一次性申请 , 申请完成后锁就可以释放了 。
也就是说,批量插入数据的语句,之所以需要这么设置 , 是因为“不知道要预先申请多少个 id” 。
既然预先不知道要申请多少个自增 id,那么一种直接的想法就是需要一个时申请一个 。但如果一个 select … insert 语句要插入 10 万行数据,按照这个逻辑的话就要申请 10 万次 。显然,这种申请自增 id 的策略,在大批量插入数据的情况下,不但速度慢,还会影响并发插入的性能 。
因此,对于批量插入数据的语句,MySQL 有一个批量申请自增 id 的策略:

  • 语句执行过程中,第一次申请自增 id,会分配 1 个;
  • 1 个用完以后,这个语句第二次申请自增 id,会分配 2 个;
  • 2 个用完以后,还是这个语句,第三次申请自增 id,会分配 4 个;
  • 依此类推,同一个语句去申请自增 id,每次申请到的自增 id 个数都是上一次的两倍 。




推荐阅读