深入探寻mysql自增列导致主键重复问题的原因
废话少说,进入正题。 拿到问题后,首先查看现场,发现问题表的中记录的最大值比自增列的值要大,那么很明显,当有记录进行插入时,自增列产生的值就有可能与已有的记录主键冲突,导致出错。首先想办法解决问题,通过人工调大自增列的值,保证大于表内已有的主键即可,调整后,导数据正常。问题是解决了,接下来要搞清楚问题原因,什么操作导致了这种现象的发生呢? 这里有一种可能,即业务逻辑包含更新自增主键的代码,由于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动作不会更新自增列值,导致更新后记录值大于自增列值 问题重现实验:
|
- sql-server-2008 – SSRS报告格式化表以并排显示数据
- 此版本的SQL Server – SQL Azure不支持语句’SELECT INTO’
- SQL Server 数据库主键的生成方式小结(sqlserver,mysql)
- sql – select子句中多个set-returns函数的预期行为是什么?
- mysql5.6 主从复制同步详细配置(图文)
- .net – 使用Insert()和Clear()时StringBuilder中的内存泄漏
- MYSQL无法启动提示: Default storage engine (InnoDB) is
- SQLSERVER数据类型转换
- sql – “选择更新”可防止在行不存在时插入其他连接
- CentOS 6.3下源码安装LAMP(Linux+Apache+Mysql+Php)运行环境