[MySQL Bug]bug#66301(Percona Bug#1035225)简析

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介:

———————————

先跑test case

1.创建测试表

CREATE TABLE t(

       id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,

       k INT,

       c CHAR(1),

       UNIQUE KEY(k)) ENGINE=InnoDB;

2.当顺序执行如下SQL时
SQL1–INSERT INTO t(k) VALUES (1), (2), (3) ON DUPLICATE KEY UPDATE c=’1′;
SQL2–INSERT INTO t(k) VALUES (2), (4), (5) ON DUPLICATE KEY UPDATE c=’2′;
SELECT * FROM t;
id      k       c
1       1       NULL
2       2       2
3       3       NULL
4       4       NULL
5       5       NULL
在Binlog里记录的是先SQL1,再SQL2

使用DEBUG_SYNC来模拟并发的场景,并发执行上述两个SQL时,会得到不同的结果,具体见test case
SELECT * FROM t;
id      k       c
1       1       NULL
4       2       1
5       4       1
6       5       NULL
而在备库的执行结果则是按照串行执行,执行结果为:
1       1       NULL
2       2       2
3       3       NULL
4       4       NULL
5       5       NULL


如果binlog_format为statement模式时,这种情况就会造成主备数据不一致,因为在备库是按照串行化执行的。

根据test case,其模拟的场景是SQL1插入第一行等待,SQL2完成,SQL1再插入剩余的记录。
当insert出现dup key时如下代码逻辑对next_insert_id做了调整
sql/sql_insert.cc
write_record函数
1649         if (table->next_number_field)
1650           table->file->adjust_next_insert_id_after_explicit_value(
1651             table->next_number_field->val_int());

其中
table->next_number_field->val_int()是冲突记录的主键值,这样我们就可以理清这里的逻辑了
SQL1获得的自增区间为1,2,3
SQL2获得的自增区间为4,5,6
如下执行序列:
SQL1:1 1 NULL  next_insert_id =2
SQL2:4 2 NULL
SQL2: 5 4 NULL
SQL2:6 5 NULL
SQL1: 试图插入2 2 NULL,uniquekey冲突,改为update,记录为4 2 1,
next_insert_id=4+1=5
SQL1: 试图插入5 3,NULL,主键冲突,改为update,记录为5 4 1
因此最后的结果是
1       1       NULL
4       2       1
5       4       1
6       5       NULL
问题在于即使唯一索引(非主键)冲突,也可能会调整next_insert_id(当冲突记录主键值>当前next_insert_id时)。Percona已经在MySQL Buglist上report了这个bug,并且patch已经release
patch很简单,对上述情况区别对待。给table增加了一个成员变量next_number_field_updated

当在INSERT … ON DUPLICATE KEY UPDATE后,如果自增列在UPDATE中,设置该变量值为TRUE。
这样在函数write_record中,如果遇到DUP KEY,当next_number_field_updated为TRUE时,设置next_insert_id值(按照原先的逻辑 adjust_next_insert_id_after_explicit_value),否则next_insert_id保留为当前的 table->file->insert_id_for_cur_row,也就是该记录获得的自增值。
相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
6月前
|
SQL 关系型数据库 MySQL
(十八)MySQL排查篇:该如何定位并解决线上突发的Bug与疑难杂症?
前面《MySQL优化篇》、《SQL优化篇》两章中,聊到了关于数据库性能优化的话题,而本文则再来聊一聊关于MySQL线上排查方面的话题。线上排查、性能优化等内容是面试过程中的“常客”,而对于线上遇到的“疑难杂症”,需要通过理性的思维去分析问题、排查问题、定位问题,最后再着手解决问题,同时,如果解决掉所遇到的问题或瓶颈后,也可以在能力范围之内尝试最优解以及适当考虑拓展性。
454 3
|
关系型数据库 MySQL PHP
【Bug解决】Thinkphp5 PDO::__construct(): MySQL server has gone away解决办法
【Bug解决】Thinkphp5 PDO::__construct(): MySQL server has gone away解决办法
195 0
|
SQL 缓存 关系型数据库
故障案例:MySQL唯一索引有重复值,官方却说This is not a bug
故障案例:MySQL唯一索引有重复值,官方却说This is not a bug
292 0
|
SQL Oracle 关系型数据库
这次被坑惨了,MySQL的隐式转换导致了一个线上BUG
某一天,开发问我,为什么针对一个查询会有两条记录,且其中一条记录并不符合条件select * from tablea where xxno = 170325171202362928;xxno为 170325171202362928 和 170325171202362930的都出现在结果中。 一个等值查询为什么会有另外一个不同值的记录查询出来呢? 我们一起来看看究竟!
|
SQL 关系型数据库 MySQL
MySQL慢查询日志配置与简析
MySQL慢查询日志配置与简析
169 0
|
SQL 关系型数据库 MySQL
MySQL 8.0.23上遇到一个FIND_IN_SET的BUG(一)
MySQL 8.0.23上遇到一个FIND_IN_SET的BUG(一)
159 0
MySQL 8.0.23上遇到一个FIND_IN_SET的BUG(一)
|
存储 关系型数据库 MySQL
MySQL之char、varchar类型简析
MySQL之char、varchar类型简析
393 0
MySQL之char、varchar类型简析
|
存储 关系型数据库 MySQL
MySQL之char、varchar类型简析
MySQL之char、varchar类型简析
343 0
MySQL之char、varchar类型简析
|
存储 固态存储 关系型数据库
MySQL 5.6 change buffer bug导致crash
Insert buffer 内部标识长度的位图没有正确更新,导致问题
197 0