(转)mysql自增列导致主键重复问题分析

时间:2022-03-14 09:04:09

mysql自增列导致主键重复问题分析。。。

 原文:http://www.cnblogs.com/cchust/p/3914935.html

前几天开发童鞋反馈一个利用load data infile命令导入数据主键冲突的问题,分析后确定这个问题可能是mysql的一个bug,这里提出来给大家分享下。以免以后有童鞋遇到类似问题百思不得其解,难以入眠,哈哈。废话少说,进入正题。

拿到问题后,首先查看现场,发现问题表的中记录的最大值比自增列的值要大,那么很明显,当有记录进行插入时,自增列产生的值就有可能与已有的记录主键冲突,导致出错。首先想办法解决问题,通过人工调大自增列的值,保证大于表内已有的主键即可,调整后,导数据正常。问题是解决了,接下来要搞清楚问题原因,什么操作导致了这种现象的发生呢?

这里有一种可能,即业务逻辑包含更新自增主键的代码,由于mysql的update动作不会同时更新自增列值,若更新主键值比自增列大,也会导致上述现象:记录最大值比自增主键值大。但开发反馈说这张表仅仅存在load data infile操作,不会进行更新主键操作,所以这个解释行不通。继续分析,表中含有唯一约束,会不会和唯一约束有关,线下实验模拟没有重现。后来想想会不会和主备切换有关系,因为前两天做过一次主备切换。于是乎,配合主备环境作了测试,果然和主备切换有关系,一切问题的来源都清晰了。

问题发生的前置条件:

1.mysql复制基于row模式

2.innodb表

3.表含有自增主键,并且含有唯一约束

4.load data infile 采用replace into语法插入数据【遇到重复唯一约束,直接覆盖】

问题发生的原理:

1.主库遇到重复unique约束时,进行replace操作;

2.replace在主库上面实际变化为delete+insert,但binlog记录的是update;

3.备库重做update动作,更新主键,但由于update动作不会更新自增列值,导致更新后记录值大于自增列值

问题重现实验:

准备工作

Create table test_autoinc(id int auto_increment, c1 int,c2 varchar(100),primary key(id),unique key(c1));

insert into test_autoinc(c1,c2) values(1,'abc');

insert into test_autoinc(c1,c2) values(2,'abc');

insert into test_autoinc(c1,c2) values(3,'abcdd');

insert into test_autoinc(c1,c2) values(4,'abcdd');

insert into test_autoinc(c1,c2) values(5,'abcdd');

1

操作

备注

Master

slave

2

查看自增列值

Show create table

test_autoinc\G

插入5条记录后,自增列值变为6

CREATE TABLE `test_autoinc` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`c1` int(11) DEFAULT NULL,

`c2` varchar(100) DEFAULT NULL,

PRIMARY KEY (`id`),

UNIQUE KEY `c1` (`c1`)

) ENGINE=InnoDBAUTO_INCREMENT=6DEFAULT CHARSET=utf8

CREATE TABLE `test_autoinc` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`c1` int(11) DEFAULT NULL,

`c2` varchar(100) DEFAULT NULL,

PRIMARY KEY (`id`),

UNIQUE KEY `c1` (`c1`)

) ENGINE=InnoDBAUTO_INCREMENT=6DEFAULT CHARSET=utf8

3

查看表数据

id | c1   | c2

---+------+------

1 |    1 | abc

2 |    2 | abc

3 |    3 | abcdd

4 |    4 | abcdd

5 |    5 | abcdd

id | c1   | c2

---+------+------

1 |    1 | abc

2 |    2 | abc

3 |    3 | abcdd

4 |    4 | abcdd

5 |    5 | abcdd

4

查看binlog位置

show master status\G

记录当前binlog位点,

后续可以查看replace动作产生的binlog事件

mysql-bin.000038

59242888

5

replace操作

replace into test_autoinc(c1,c2) values(2,'eeee');

影响两条记录,主库replace=

delete+insert

Query OK, 2 rows affected

(0.00 sec)

6

查看表数据

id | c1   | c2

---+------+-------

1 |    1 | abc

3 |    3 | abcdd

4 |    4 | abcdd

5 |    5 | abcdd

6 |    2 | eeee

id | c1   | c2

---+------+-------

1 |    1 | abc

3 |    3 | abcdd

4 |    4 | abcdd

5 |    5 | abcdd

6 |    2 | eeee

7

查看binlog事件

show binlog events in 'mysql-bin.000038' from 59242888;

也可以通过mysqlbinlog工具分析日志,查询从库执行的update语句

Pos      | Event_type

---------+---------------

59242888 | Query

59242957 | Table_map

59243013 |Update_rows_v1

59243072 | Xid

8

查看自增列值

Show create table

此时master的自增列为7,而slave的自增列为6,与表内最大值相同

CREATE TABLE `test_autoinc` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`c1` int(11) DEFAULT NULL,

`c2` varchar(100) DEFAULT NULL,

PRIMARY KEY (`id`),

UNIQUE KEY `c1` (`c1`)

) ENGINE=InnoDBAUTO_INCREMENT=7

CREATE TABLE `test_autoinc` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`c1` int(11) DEFAULT NULL,

`c2` varchar(100) DEFAULT NULL,

PRIMARY KEY (`id`),

UNIQUE KEY `c1` (`c1`)

) ENGINE=InnoDBAUTO_INCREMENT=6

经过第8步操作后,若发生主备切换,slave提供服务,此时通过自增列插入主键6的记录,就会发生主键冲突。

如何解决这个bug?对于replace操作,生成binlog时也生成delete和insert两个事件而非一个update事件;或者在执行update更新主键的同时也更新自增列值。当然了,这个只是纯原理分析,具体采用什么方法解这个问题,要根据mysql内部的实现,避免引入新的问题。这个bug我同事已经提交到社区,http://bugs.mysql.com/73563 ,大家可以看看。

(转)mysql自增列导致主键重复问题分析的更多相关文章

  1. mysql自增列导致主键重复问题分析。。。

    前几天开发童鞋反馈一个利用load data infile命令导入数据主键冲突的问题,分析后确定这个问题可能是mysql的一个bug,这里提出来给大家分享下.以免以后有童鞋遇到类似问题百思不得其解,难 ...

  2. mysql insert插入时实现如果数据表中主键重复则更新,没有重复则插入的四种方法

    [CSDN下载] Powerdesigner 设计主键code不能重复等问题 [CSDN博客] Oracle中用一个序列给两个表创建主键自增功能的后果 [CSDN博客] MySQL自增主键删除后重复问 ...

  3. MySql数据库查询表信息/列信息(列ID/列名/数据类型/长度/精度/是否可以为null/默认值/是否自增/是否是主键/列描述)

    查询表信息(表名/表描述): SELECT table_name name,TABLE_COMMENT value FROM INFORMATION_SCHEMA.TABLES WHERE table ...

  4. SqlServer数据库查询表信息/列信息(列ID/列名/数据类型/长度/精度/是否可以为null/默认值/是否自增/是否是主键/列描述)

    查询表信息(表名/表描述) Value ) AS value FROM sysobjects a Where a.xtype = 'U' AND a.name <> 'sysdiagram ...

  5. Oracle数据库查询表信息&sol;列信息&lpar;列ID&sol;列名&sol;数据类型&sol;长度&sol;精度&sol;是否可以为null&sol;默认值&sol;是否自增&sol;是否是主键&sol;列描述&rpar;

    查询表信息(表名/表描述) Select table_Name As Name,Comments As Value From User_Tab_Comments Where table_Type='T ...

  6. PostgreSql数据库查询表信息&sol;列信息&lpar;列ID&sol;列名&sol;数据类型&sol;长度&sol;精度&sol;是否可以为null&sol;默认值&sol;是否自增&sol;是否是主键&sol;列描述&rpar;

    查询表信息(表名/表描述) select a.relname as name , b.description as value from pg_class a ) b on a.oid = b.obj ...

  7. Mysql 多列形成主键(复合主键 )

    什么是数据表的复合主键 所谓的复合主键 就是指你表的主键含有一个以上的字段组成 比如 create table test (    name varchar(19),    id number,    ...

  8. (2&period;10)Mysql之SQL基础——约束及主键重复处理

    (2.10)Mysql之SQL基础——约束及主键重复处理 关键词:mysql约束,批量插入数据主键冲突 [1]查看索引: show index from table_name; [2]查看有约束的列: ...

  9. 【Five-Minute Share】&OpenCurlyDoubleQuote;为什么要选择自增型的主键”

    我们在开发的时候经常会听到这样的建议:1. 设计数据库表的时候,要为每个表设置一个主键:2. 主键最好是跟业务无关的: 3. 最好是自增的: 于是,很多新入行的程序猿们把这些前辈们的教条拿来就用,每个 ...

随机推荐

  1. MySQL 优化之 MRR &lpar;Multi-Range Read&colon;二级索引合并回表&rpar;

    MySQL5.6中引入了MRR,专门来优化:二级索引的范围扫描并且需要回表的情况.它的原理是,将多个需要回表的二级索引根据主键进行排序,然后一起回表,将原来的回表时进行的随机IO,转变成顺序IO.文档 ...

  2. android开发--多线程

    android中的几种多线程实现方式: 1)Activity.runOnUiThread(Runnable) 2)View.post(Runnable) ;View.postDelay(Runnabl ...

  3. 在MVC3中修改KindEditor实现图片删除

    编辑器KindEditor可以上传图片,但却不能删除图片,因此我们通过修改一些文件,对KindEditor进行扩展,使得KindEditor能删除服务器上的图片. 主要方法就是:在图片空间中浏览图片, ...

  4. WebKit渲染基础(转载 学习中。。。)

    概述 WebKit是一个渲染引擎,而不是一个浏览器,它专注于网页内容展示,其中渲染是其中核心的部分之一.本章着重于对渲染部分的基础进行一定程度的了解和认识,主要理解基于DOM树来介绍Render树和R ...

  5. &lbrack;Everyday Mathematics&rsqb;20150104

    设 $a>0$, $$\bex x_1=1,\quad x_{n+1}=x_n+an\prod_{i=1}^n x_i^{-\frac{1}{n}}. \eex$$ 试证: $$\bex \vl ...

  6. mysqldump原理2

    本文主要探讨 mysqldump 的几种主要工作方式,并且比较一下和 mk-parralel-dump的一些差异,为备份方式的选择提供更多的帮助. 首先来看下 mysqldump 的几个主要参数的实际 ...

  7. ExtJS 4 Grids 详解

    Grid Panel是ExtJS最常用的组件之一,它的功能非常丰富,提供了非常便捷的方法执行排序,分组,编辑数据. Basic Grid Panel 基本表格面板 让我们创建一个简单的表格,这有创建和 ...

  8. 【转载】Java线程面试题 Top 50

    Java线程面试题 Top 50 2014/08/21 | 分类: 基础技术 | 4 条评论 | 标签: 多线程, 面试题 分享到:140 本文由 ImportNew - 李 广 翻译自 javare ...

  9. face detection&lbrack;CNN casade&rsqb;

    本文是基于< A convolutional neural network cascade for face detection>的解读,所以时间线是2015年. 0 引言 人脸检测是CV ...

  10. ThinkPHP框架 AJAX方法返回 AJAX实现分页例子:

    在模块控制器Controller文件夹里创建一个 FenyeController.class.php控制器 <?php namespace Admin\Controller; use Think ...