对于那些向带有自增列的表中插入行的语句,Innodb提供一种可配置的锁定机制,这种锁定机制可以显著提高SQL语句的可伸缩性和性能。
Innodb中为了使用自增机制,自增列必须是索引的部份,从而可以使用等价查询。典型的做法是将自增列放在表的索引的第一个位置。
 
Innodb自增锁模式
自增锁模式是在启动的时候由参数innodb_autoinc_lock_mode指定的。
 
在讲innodb_autoinc_lock_mode之前,先了解一下以下名词:
--"insert-like"语句
  在表中产生新行的语句,比如insert、insert...select、replace、replace...select、load data。也包含"simple-inserts"、"bulk-inserts"、"mixed-mode"插入。
 
--"simple-inserts"
  语句执行前可以提前知道要插入多少行。包含不含有子查询的单行插入、多行插入和单行replace、多行replace。但是不包含insert... on duplicate key update。
 
--"bulk inserts"
  插入的行数数量是不知道的。包含insert... select,replace...select,load data,而不是简单的插入。innodb每处理一行就给自增列指定一个新值。
 
--"mixed-mode inserts"
  类似simple-inserts,但是不是所有的自增列都被指定值。例如t1表中c1列是自增列:  
  1. insert into t1(c1,c2) values(1,'a'),(null,'b'),(5,'c'),(null,'d')

  另一种"mixed-mode inserts"是insert...on duplicate key update,最差的场景就是一条insert后跟着一条update,产生的自增列的值可能都没有用到。

 
innodb_autoinc_lock_mode有三种配置值:0、1、2
-0表示"traditional"
  传统锁模式的行为跟5.1之前一样,即没有出现该参数的时候一样。主要是为了向后兼容,性能测试等。
  在这种模型下,insert-like语句使用表级别的auto-inc锁来插入自增值。锁通常是持有到语句结束(不是事务结束)。
  对于给定的一些列插入语句,自增值的产生是可预测和可重复有序的,且是连贯的。
 
  对于基于语句的复制,在slave端的一条语句的自增值和在master端是一样的。如果多个语句是交错的,那么slave端两个并发语句的结果可能是不一致的。
 
示例:
首先有张表:
  1. create table t1(
  2. c1 int(11) not null auto_increment,
  3. c2 varchar(10) default null,
  4. primary key(c1)
  5. ) engine = innodb;
假设有两个事务插入数据:
  1. tx1: insert into t1 (c2) select 1000 rows from another table ... #事务1插入1000行
  2. tx2: insert into t1 (c2) values ('xxx');

innodb无法提前知道tx1会插入多少条数据,只好每插入一条数据就产生一个自增值。对于表级锁,每次执行执行一条sql语句,所以对于不同的sql语句,自增值的产生不是交错的。

tx1产生的自增值是连续的,tx2中单独的自增值要么比tx1中的小,要么比其大。取决于哪个事务先执行。
 
在基于语句的复制或恢复场景,只要二进制中的sql执行是按照相同的顺序,结果就会和tx1和tx2的结果一致。所以表级锁对基于语句的复制时是安全的。但是表级锁会限制并发性和扩展性。
 
在上面的例子中,如果没有表级锁,tx2中产生的自增值的准确性取决于其运行时间,如果运行时恰好tx1也在运行,最后结果是不可确定的,多次测试的结果也是不同的。
 
在consecutive锁模式下,innodb避免了使用表级别的auto-inc锁来控制"simple-insert"语句。
如果不使用二进制日志去replay语句来恢复或者复制,可以使用"interleaved"模式的锁,从而避免使用表级auto-inc锁,而且能够支持大的并发和提升性能,代价是自增值会产生gap。
 

·1表示"consecutive"锁模式

这是默认的锁定模式。在这种模式下,“bulk inserts”使用特殊的AUTO-INC表级锁并将其保持到语句结束。这适用于所有INSERT ... SELECT,REPLACE ... SELECT和LOAD DATA语句。一次只能执行一条持有AUTO-INC锁的语句。如果批量插入操作的源表与目标表不同,则在对源表中选择的第一行加共享锁之后,将对目标表执行AUTO-INC锁。如果批量插入操作的源和目标在同一表中,则在对所有选定行施加共享锁之后,获取AUTO-INC锁。

"Simple inserts"可以提前知道需要哪些自增值,在mutex的帮助下,不需要对表加上标级auto-inc锁。mutex只是在分配自增值得时候存在,不需要等整个sql语句结束才释放。如果有另外的事务持有auto-inc锁得时候,就需要获取表级auto-inc锁了。

此锁模式可确保在存在INSERT语句的情况下(事先不知道行数)(并且随着语句的进行自动分配自增值),所有由“insert-like”语句分配的自动递增值语句是连续的,并且操作对于基于语句的复制是安全的。

简而言之,此锁模式可提高可伸缩性,同时可安全地用于基于语句的复制。此外,与“传统”锁定模式一样,任何给定语句分配的自动增量编号都是连续的。对于任何使用自增的语句,与“传统”模式相比,语义没有任何变化,但有一个重要的例外。

"mixed-mode inserts"例外,其中用户为多行"simple insert"中的某些(但不是全部)行的AUTO_INCREMENT列提供了显式值。对于此类插入,InnoDB分配的自增值比要插入的行数更多。但是,所有自动分配的值都是连续生成的(因此高于由最近执行的先前语句生成的自增值)。"多余"的自增值被丢失。

·2表示"interleaved"锁模式

在这种锁模式下,没有"insert-like"语句使用表级的AUTO-INC锁定,并且可以同时执行多个语句。这是最快,最具扩展性的锁定模式,但是当使用基于语句的复制或恢复方案从二进制日志中重放SQL语句时,这是不安全的。

在这种锁模式下,保证自增值是唯一的,并且在所有同时执行的"insert-like"语句中单调递增。但是,由于多个语句可以同时生成数字(也就是说,在语句之间交错分配数字),因此为任何给定语句插入的行生成的值可能不是连续的。

如果仅执行的语句是"insert-like",为单个语句生成的数字中没有空格。其中要提前知道要插入的行数,则为“除混合模式插入”外,为单个语句生成的数字中没有空格。但是,执行"bulk-inserts"时,任何给定语句分配的自增值可能存在间隙。

Innodb自增锁的使用
1.使用自增列进行复制
如果使用基于语句的复制,innodb_autoinc_lock_mode设置为0或1(主、备都使用相同的配置)。如果是设置为2或者主备设置不一样,不能保证准备端一致。

如果是使用基于行的、混合模式的复制,所有自增锁模式都是安全的,因为基于行的复制对sql的执行顺序是不敏感的(混合模式会将基于语句的不安全的复制转换成行复制)。

2.自增值的丢失和序列空隙(sequence gaps)
在所有自增锁模式中(0,1,2),如果使用自增值得事务发生了回滚,这些自增值就丢失了。这些值是不可以重用的,这样就产生了gap。

3.自增列指定null或0值
在所有自增锁模式中(0,1,2),如果将自增列指定为null或0,innodb会自行给自增列赋值

4.自增列指定为负值
可以插入赋值,但是不能在负值得基础上进行自增

5.超过自增列指定的最大值
超过自增列指定的最大值就不能自增了。

6."mixed-mode inserts"中自增值得使用
"mixed-mode inserts"中有"simple insert"指定的自增值,也有没有指定的。在不同的自增锁模式下结果是不同的。

7.在插入的过程中修改自增值
会导致重复的值。

Innodb自增计数器的初始化
创建了自增列后,对应的数据字典中包含一个自增计数器,用来为列赋值。这个计数器是存储在内存中,而不是磁盘上。

在实例启动后,innodb会执行类似下面的语句来为计数器初始化:
select max(ai_col) from table_name for update;
缺省情况下,会将获取的值增加1。也可以修改参数auto_increment_increment进行配置。

如果表是空的,计数器的值就是1。

MySQL -- Innodb是如何处理自增列的的更多相关文章

  1. MySQL面试题之为什么要为innodb表设置自增列做主键?

    为什么要为innodb表设置自增列做主键? 1.使用自增列做主键,写入顺序是自增的,和B+数叶子节点分裂顺序一致 2.表不指定自增列做主键,同时也没有可以被选为主键的唯一索引,InnoDB就会选择内置 ...

  2. mysql 深度解析auto-increment自增列"Duliplicate key"问题

    转载自:https://cloud.tencent.com/developer/article/1367681 问题描述 近期,线上有个重要Mysql客户的表在从5.6升级到5.7后master上插入 ...

  3. mysql iot 主键自增列问题

    mysql 如何避免热点块? 主键按sn自增列 Oracle 可以通过翻转索引 比如 插入101 102 103 104 变成101 201 301 401 分散数据 反转索引坏处,无法index r ...

  4. MySQL innodb的组合索引各个列中的长度不能超过767,

    MySQL索引的索引长度问题   MySQL的每个单表中所创建的索引长度是有限制的,且对不同存储引擎下的表有不同的限制. 在MyISAM表中,创建组合索引时,创建的索引长度不能超过1000,注意这里索 ...

  5. MySQL使用AUTO_INCREMENT列的表注意事项之update自增列篇

    1)对于MyISAM表,如果用UPDATE更新自增列,如果列值与已有的值重复,则会出错:如果大于已有的最大值,则会自动更新表的AUTO_INCREMENT,操作是安全的. (2)对于innodb表,u ...

  6. MySQL--自增列学习

    ##=====================================================================================## 在数据库表设计中会纠 ...

  7. MySQL--自增列持久化问题

    ====================================================================== 自增列持久化问题 5.5/5.6/5.7三个版本中,MyS ...

  8. [MySQL FAQ]系列 — 为什么InnoDB表要建议用自增列做主键

    我们先了解下InnoDB引擎表的一些关键特征: InnoDB引擎表是基于B+树的索引组织表(IOT): 每个表都需要有一个聚集索引(clustered index): 所有的行记录都存储在B+树的叶子 ...

  9. (转)mysql中InnoDB表为什么要建议用自增列做主键

    InnoDB引擎表的特点 1.InnoDB引擎表是基于B+树的索引组织表(IOT) 关于B+树 (图片来源于网上) B+ 树的特点: (1)所有关键字都出现在叶子结点的链表中(稠密索引),且链表中的关 ...

随机推荐

  1. 【医疗行业】关于dcm4che DICOM Toolkit:C-Move与C-Get

    在医学影像领域,DICOM标准与dcm4che的重要性毋庸置疑.幸好,这些开源的dcm4che DICOM 工具包,能对我们提供不少帮助. 在这里有很多的工具: Sources: https://gi ...

  2. 快速生成100W条数据

    快速生成100W条数据,生成的时候是顺序生成,取的时候是随机取用,生成100W条数据大概一分多钟,比网上其他代码速度要快很多 )) --truncate table tb --select top 1 ...

  3. PhpStorm 2017.1安装及破解过程

    1.下载原安装文件和破解文件:magnet:?xt=urn:btih:7FD357910B7AFBFC8FBA3647A2FAC8F15F0D02F0  (直接放到迅雷里下载) 2.Licence S ...

  4. 神经网络:caffe特征可视化的代码例子

    caffe特征可视化的代码例子 不少读者看了我前面两篇文章 总结一下用caffe跑图片数据的研究流程 deep learning实践经验总结2--准确率再次提升,到达0.8.再来总结一下 之后.想知道 ...

  5. Selenium+TestNG+Jenkins 框架图形化UML表示

  6. foxmail怎么设置个性签名

    foxmail是我们日常使用的邮件客户端之一,相信很多的朋友都在使用.那么,我们在发邮件的时候,很多朋友都会使用一个个性签名,那么对于foxmail的邮件签名怎么来设置呢?今天笔者就来给大家分享一下, ...

  7. Fix problems that block programs from being installed or removed

    Follow these steps to automatically repair issues including corrupted registry keys that block you f ...

  8. RHEL6.5 grub修复测试

    RHEL6.5 grub修复测试 1.删除系统中的grub.conf配置文件,然后重启系统#rm -f /boot/grub/grub.conf#reboot 2.重启后,系统进入到grub界面:gr ...

  9. 转:开源3D引擎介绍

    Delta3D:Delta3D是一个功能齐全的游戏引擎,可用于游戏,模拟或其他图形应用.其模块化设计集成了其他的开源项目,如‘开放场景图’,‘开放动力学引擎’,‘人物动画库’和‘OpenAL’ .De ...

  10. Arduino和C51开发OLED显示屏

    技术:51单片机.Arduino.OLED显示屏.U8glib   概述 OLED显示屏常常用作为智能产品的显示设备,本文简单介绍OLED显示屏的使用方法. 详细 代码下载:http://www.de ...