背景:

  Innodb引擎使用B_tree结构保存表数据,这样就需要一个唯一键表示每一行记录(比如二级索引记录引用)。

  Innodb表定义中处理主键的逻辑是:

  1.如果表定义了主键,就使用主键唯一定位一条记录

  2.如果没有定义主键,Innodb就生成一个全局唯一的rowid来定位一条记录

auto_increment的由来:

  1.Innodb强烈推荐在设计表中自定义一个主键,因为rowid是全局唯一的,所以如果有很多表没有定义主键,就会在生成rowid上产生争用。

      /* Dictionary system struct */
struct dict_sys_struct{
mutex_t mutex;
row_id_t row_id;
......
}

  row_id由mutex保护,并在每次checkpoint的时候,写入到数据字典的文件头。

  2.当用户自定义了主键后,由于大部分实际应用部署的分布式,所以主键值的生成上,采用集中式的方式,更容易实现唯一性,所以auto_increment非常合适。

  auto_increment也带来两个好处:

  1. auto_increment的值是表级别的,不会在db级别上产生争用

  2. 由于auto_increment的顺序性,减少了随机读的可能,保证了写入的page的缓冲命中。(不可否认,写入的并发足够大时,会产生热点块的争用)

auto_increment引起的bug:

  环境:MySQL 5.6.16版本, binlog_format=row

  case复现:

     create table test.kkk ( c int(11) default null, id int(11) not null auto_increment, d int(11) default null, primary key (id), unique key d (d) )
engine=innodb default charset=latin1;
insert into test.kkk values(5, 27,4);
replace into test.kkk(c, id, d) values(6, 35, 4);
commit;
     show create table时:
主库:auto_increment=36
备库:auto_increment=28

  当进行主备切换后,导致主键冲突,slave恢复异常。

  同样insert on duplication update 语句同样存在这样的问题。

aliyun rds分支bug修复

  问题的原因:Innodb对于auto_increment的处理,当语句是insert时,会进行递增,而update,delete语句则不更新。

  当replace语句在主库的执行时:

  1. 先按照insert语句执行,发现uk冲突。

  2. 演变成update语句进行更新。

  这样在主库,虽然insert失败,但auto_increment也递增上去了。但到备库,row格式下,只产生了一个update row event,

  备库无法知道主库是一个replace语句,而且insert还失败了, 所以auto_increment在备库没有递增。

  修复方式:在备库,对于update进行auto_increment递增,可能会产生副作用,即auto_increment的浪费,但不会产生主键冲突。

那些年经历的auto_increment坑:

  1. 实例重启,主键冲突:

  内存中的autoinc值,在系统重启后,使用select max(id) from table来初始化。所以,如果你设计的业务表,存在delete操作,那么一旦你的实例crash过,重启后,可能会复用以前使用过的id值。如果你需要持续对这个表进行逻辑备份,那么就可能会碰到主键冲突的问题。

  2. load file阻塞:

  在设置innodb_autoinc_lock_mode=1的时候,MySQL为了维护单个statement语句的id连续性,当不确定插入条数的时候,会在语句整个执行过程中

  持有LOCK_AUTO_INC, /* locks the auto-inc counter of a table in an exclusive mode */

  这个锁是表级别的,使用互斥模式。

  所以,在繁忙的表上,如果要导入数据,小心可能阻塞正常的业务写入,并发写入在这个时候也会阻塞的。

MySQL auto_increment的坑的更多相关文章

  1. [MySQL] AUTO_INCREMENT lock Handing in InnoDB

    MySQL AUTO_INCREMENT lock Handing in InnoDB 在MySQL的表设计中很普遍的使用自增长字段作为表主键, 实际生产中我们也是这样约束业务开发同学的, 其中的优势 ...

  2. 服务器安装mysql遇到的坑

    服务器安装mysql遇到的坑 一.CentOS7安装MySQL 1.下载:MySQL官方的 Yum Repository wget -i -c http://dev.mysql.com/get/mys ...

  3. EF6(CodeFirst)+MySql开发脱坑指南

    废话 话说当年,在一个春光明媚的晌午,邂逅了迷人的丁香姑娘,从此拜倒在了她的石榴裙下,至今不能自拔,这位丁香姑娘就是ORM思想. 所谓ORM思想,我的理解就是根据一定的规则,把程序中的对象和数据库中的 ...

  4. Mac安装mysql遇到的坑

    使用XMPP前安装了mysql,小白遇到好多坑,不要见怪 mysql官网下载,选择Community中扩展名为dmg的文件 安装完成后要记住密码,重要的事情只说一遍,对了,安装时也没有偏好设置和自启动 ...

  5. MySQL大小写补坑记

    背景:由于项目开始时数据库设计经验不足,数据库名和部分数据表名都含有大写字母.但问题是,Linux上数据库名和表名是区分大小写的,而Windows上是不区分大小写的.结果就是在看本地的数据库的时候,对 ...

  6. 验证:mysql AUTO_INCREMENT 默认值是1

    用mongodb时,有些字段需要做自增,而且是用二十进制字母表示(使用a-t对应0-19),做了一个_auto_increment字段用来保存,但是应该从0开始还是从1开始呢? 和mysql保持一致便 ...

  7. MySQL Auto_Increment属性应用

        我们经常要用到唯一编号,以标识记录.在MySQL中可通过数据列的AUTO_INCREMENT属性来自动生成.MySQL支持多种数据表,每种数据表的自增属性都有差异,这里将介绍各种数据表里的数据 ...

  8. MySQL auto_increment实现

    http://www.cnblogs.com/xpchild/p/3825309.html 运维的时候,经常遇到auto_increment的疑惑: 机器异常crash,重启后id回退的问题 性能考虑 ...

  9. MySQL AUTO_INCREMENT 简介

    可使用复合索引在同一个数据表里创建多个相互独立的自增序列,具体做法是这样的:为数据表创建一个由多个数据列组成的PRIMARY KEY OR UNIQUE索引,并把AUTO_INCREMENT数据列包括 ...

随机推荐

  1. fedora下缺少autopoint包的解决办法

    编译过程中,报错,缺少autopoint包 然而无论是yum install autopoint 还是yum search autopoint都没有理想的答案 执行yum install gettex ...

  2. package.json 字段全解析 share

    Name 必须字段. 小提示: 不要在name中包含js, node字样: 这个名字最终会是URL的一部分,命令行的参数,目录名,所以不能以点号或下划线开头: 这个名字可能在require()方法中被 ...

  3. LAMP环境 源码包安装

    linux的学习很早就开始了,大学的时候的时候有有学过unix,后来每年都有去看看linux,因为在小城市的缘故,很少会实际工作中用到,基本都是智慧云之类的,同事也说,你学起来也用不上,IT生态不好, ...

  4. yii2 学习中

    属性: public function __get($name) // 这里$name是属性名 { $getter = 'get' . $name; // getter函数的函数名 if (metho ...

  5. 248. Strobogrammatic Number III

    题目: A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at ups ...

  6. Android 显示原理简介

    作者:yearzhu,2011年进入腾讯公司,从事过Web端及移动端的测试工作,喜爱新鲜事物及新技术,目前在SNG开放平台测试组负责的移动互联SDK的测试工作. 现在越来越多的应用开始重视流畅度方面的 ...

  7. Android title和actionbar的区别

    我想在一个页面的顶端放入两个按钮,应该用title还是actionbar.他们两个什么区别?分别该什么时候用? 答: android title 是UI上的一小部分,它支持Text和Color,你可以 ...

  8. 关于为什么java需要垃圾回收

    为什么java采用垃圾回收而c++却不采用,这是因为在java中,所有对象变量都是引用,当一个引用被新对象覆盖掉时,就没有引用指向原来的对象了,这个对象就“失控了”. 而C++中,除非使用特殊符号&a ...

  9. QTP之对测试用例的自动化过程的分解

    第一部分:自动化一个测试用例 当你要开始自动化一个测试用例的时候,有一些重要的事情需要完成.当你完成所有这些事情的时候,测试脚本的自动化也随之完成. 在这里,我们将首先在大部分的自动化测试用例里找出所 ...

  10. Classpath entry org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER will not be exported

    打开navigator,修改下面的classpath文件: 将<classpathentry kind="con" path="org.maven.ide.ecli ...