(转)mysql自增列导致主键重复问题分析
mysql自增列导致主键重复问题分析。。。
前几天开发童鞋反馈一个利用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自增列导致主键重复问题分析的更多相关文章
- mysql自增列导致主键重复问题分析。。。
前几天开发童鞋反馈一个利用load data infile命令导入数据主键冲突的问题,分析后确定这个问题可能是mysql的一个bug,这里提出来给大家分享下.以免以后有童鞋遇到类似问题百思不得其解,难 ...
- mysql insert插入时实现如果数据表中主键重复则更新,没有重复则插入的四种方法
[CSDN下载] Powerdesigner 设计主键code不能重复等问题 [CSDN博客] Oracle中用一个序列给两个表创建主键自增功能的后果 [CSDN博客] MySQL自增主键删除后重复问 ...
- MySql数据库查询表信息/列信息(列ID/列名/数据类型/长度/精度/是否可以为null/默认值/是否自增/是否是主键/列描述)
查询表信息(表名/表描述): SELECT table_name name,TABLE_COMMENT value FROM INFORMATION_SCHEMA.TABLES WHERE table ...
- SqlServer数据库查询表信息/列信息(列ID/列名/数据类型/长度/精度/是否可以为null/默认值/是否自增/是否是主键/列描述)
查询表信息(表名/表描述) Value ) AS value FROM sysobjects a Where a.xtype = 'U' AND a.name <> 'sysdiagram ...
- Oracle数据库查询表信息/列信息(列ID/列名/数据类型/长度/精度/是否可以为null/默认值/是否自增/是否是主键/列描述)
查询表信息(表名/表描述) Select table_Name As Name,Comments As Value From User_Tab_Comments Where table_Type='T ...
- PostgreSql数据库查询表信息/列信息(列ID/列名/数据类型/长度/精度/是否可以为null/默认值/是否自增/是否是主键/列描述)
查询表信息(表名/表描述) select a.relname as name , b.description as value from pg_class a ) b on a.oid = b.obj ...
- Mysql 多列形成主键(复合主键 )
什么是数据表的复合主键 所谓的复合主键 就是指你表的主键含有一个以上的字段组成 比如 create table test ( name varchar(19), id number, ...
- (2.10)Mysql之SQL基础——约束及主键重复处理
(2.10)Mysql之SQL基础——约束及主键重复处理 关键词:mysql约束,批量插入数据主键冲突 [1]查看索引: show index from table_name; [2]查看有约束的列: ...
- 【Five-Minute Share】“为什么要选择自增型的主键”
我们在开发的时候经常会听到这样的建议:1. 设计数据库表的时候,要为每个表设置一个主键:2. 主键最好是跟业务无关的: 3. 最好是自增的: 于是,很多新入行的程序猿们把这些前辈们的教条拿来就用,每个 ...
随机推荐
- modelsim读写TXT文件
//open the file Initial Begin step_file = $fopen("F:/Company/Src/txt/step.v","r" ...
- SPSS-Friedman 秩和检验-非参数检验-K个相关样本检验 案例解析
三人行,必有我师,是不是真有我师?三种不同类型的营销手段,最终的营销效果是否一样,随即区组秩和检验带你进入分析世界 今天跟大家讨论和分享一下:spss-Friedman 秩和检验-非参数检验-K个(多 ...
- hdu1257 最少拦截系统(贪心) 2016-05-19 20:28 90人阅读 评论(0) 收藏
最少拦截系统 Problem Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能 ...
- 让cxGrid像Excel那样高亮显示选区的行号列标
http://www.oschina.net/code/snippet_54100_1102 Developer Express的cxGrid控件是一个相当有特色的数据栅格组件,支持自动分组.卡片式显 ...
- delphi TStringList 用法详解
转自: http://blog.163.com/you888@188/blog/static/67239619201472365642633/ delphi TStringList 用法详解 2014 ...
- 拷贝构造函数——防篡改
对于普通类型的对象来说,他们之间的复制是简单的,比如: int a = 88; int b = a; 而类和普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量. #include <io ...
- Android-Git命令行操作
Git命令行操作,在Mac上使用的话,Mac会自带了Git,直接在终端或者iTerm都可以执行Git命令操作: Git命令行操作,在Windows系统电脑上使用的话,需要安装Git,安装好Git ...
- Linux服务器目录空间不足解决措施
一般情况下工作环境中我们的服务或数据库文件都会存储在一个单独挂载的分区中,一般占空间比较大的大多就是服务的运行日志以及数据库文件,当我们分区的可用空间不足时就需要我们对分区进行扩容,或者找其它方法 ...
- WPF/Silverlight开发的15个最佳实践(转发)
英文出处:http://www.kunal-chowdhury.com/2010/08/some-best-practices-for-silverlight.html 作者:Kunal Chowdh ...
- 在Windows 7上安装Team Foundation Server(TFS)的代理服务器(Agent)
自2009年微软发布Windows 7以来,经过8年的市场验证,Windows 7已经成为史上应用最为广泛的操作系统.但是面对技术变化的日新月异,2015年微软正式停止了对Windows 7的主流支持 ...