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

———————————

先跑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,也就是该记录获得的自增值。

时间: 2024-11-02 01:38:03

[MySQL Bug]bug#66301(Percona Bug#1035225)简析的相关文章

bugzilla 软件测试-bugzilla创建两个产品后,新建bug,不出bug填写界面!!!

问题描述 bugzilla创建两个产品后,新建bug,不出bug填写界面!!! 各位大侠,本人小白,今天设置完bugzilla后,在产品中新建了一个产品后,点击新建bug,出现bug填写界面,然后再填写了一个产品,点击新建bug,不是跳转到新建bug界面,而是出现如下信息: 此页面可让你编辑预设的使用偏好值. 每项偏好的「预设值」将会适用于所有未选择自己的偏好设置的使用者,以及未登入的访客. 「启用」的勾选框控制此一偏好值是否可供使用者选用. 如果勾选,使用者可以在他们的偏好设置页面看见此一偏好

大数据相关概念的界定与简析

通过对大数据相关概念进行明确界定,企业可以正确地规划自己的数据体系,并且对传统的技术方法与新兴的技术方法进行合适地定位. IT技术迅猛发展,新技术层出不穷,但业界却普遍对许多基本概念产生混淆.在当今最为流行的大数据领域也出现了这样的情况.结构化数据.非结构化数据等概念被频繁引用,却各方往往各执一词.对数据概念的混淆已经在很大程度上影响了企业对其数据体系进行清晰.正确的规划.本文的作者从实际工作出发,试图对一些关键的大数据相关概念给出明确的定义,并进行简要的解析. 一.按数据特征分类 ■结构化数据

Rails系统中的AJAX开发技术简析(2)

ajax|rails 五. 使用link_to_remote Rails有若干帮助者方法以在你的视图的模板中实现Ajax.一种最简单且很通用的方法就是link_to_remote().让我们考察一个简单的web页面-它实现询问时间并且有一个链接,用户可以点击这个链接来获得当前的时间.该应用程序经由link_to_remote()使用Ajax以检索时间并且显示它于web页面. 我的视图模板(index.rhtml)看起来象: <html><head><title>Ajax

Rails系统中的AJAX开发技术简析(3)

ajax|rails 六. 使用form_remote_tag 这个form_remote_tag()帮助函数与link_to_remote()很相似,除了它也发送一个HTML表单的内容之外.这意味着该行动处理器可以使用用户输入的数据来形成响应.这个实例显示了一个web页面-它有一个列表和一个支持Ajax的表单-该表单能够让用户添加一些选项到该列表中. 我的视图模板(index.rhtml)看上去象: <html><head><title>Ajax List Demo&

简析JAVA的XML编程

xml|编程  个人认为这篇文章通俗易懂,值得推荐.    XML作为全球通用的结构化语言,越来越受人们青睐,各种开发平台(比如Microsoft Studio系列.Oracle系列.Inprise Borland系列等)也都把支持XML开发作为宣传口号之一 .由于笔者所从事的电子政务开发较早的引入了XML,所以尝到了许多甜头,在许多项目中利用XML数据交换信息,省去了许多麻烦事,不用制定繁锁的数据格式,利用XML数据易于表达,也利于一线开发者跟踪调试.         笔者先前也曾发表过相关的

ORA-12913: 错误简析,及处理心得

错误|心得                                    ORA-12913: 错误简析,及处理心得     事先声明,因为工作变动,偶有整一年没有摸过ORACLE了,呵呵    昨天晚上装完ORACLE后,准备创建属于自己的表空间的时候,出现了ORA-12913: 无法创建字典管理的表空前. 当然了,故障排除很简单,找到文档,看一眼就排除了. 但既然在ORACLE9I之后,系统缺省安装时为本地管理表空间(Local Managed Tablespace)LMT,好处多多

ug建模以后有限元分析的步骤简析

  ug建模以后有限元分析的步骤简析.许多正在学习ug这个软件的网友最近都在议论一个问题,那就是:ug怎么进行有限元分析.要解决这个问题,我们需要先来了解一下什么是ug有限元分析.而网上关于ug有限元分析的教程还是挺多的,但是,小编总结了一下规律之后发现,ug有限元分析的步骤基本上离不开8个步骤,下面,就一起来看看今天的ug建模以后有限元分析的步骤简析! ug有限元分析 推荐:ug4.0软件下载 什么是ug有限元分析? 有限元分析(FEA,Finite Element Analysis)利用数学

实例简析SQL嵌套子查询

  实例简析SQL嵌套子查询: 一些初级程序员常常对SQL语法中的子查询,由其对嵌套子查询(子查询中包含一个子查询)的使用比较生疏,本文就此做一个基本讲解,相信新手会有一定收获. 使用子查询的原则 1.一个子查询必须放在圆括号中. 2.将子查询放在比较条件的右边以增加可读性. 子查询不包含 ORDER BY 子句.对一个 SELECT 语句只能用一个 ORDER BY 子句, 并且如果指定了它就必须放在主 SELECT 语句的最后. ORDER BY 子句可以使用,并且在进行 Top-N 分析时

从底层简析Python程序的执行过程

  这篇文章主要介绍了从底层简析Python程序的执行过程,包括注入操作码和封装程序等解释器执行层面的知识,需要的朋友可以参考下 最近我在学习 Python 的运行模型.我对 Python 的一些内部机制很是好奇,比如 Python 是怎么实现类似 YIELDVALUE.YIELDFROM 这样的操作码的;对于 递推式构造列表(List Comprehensions).生成器表达式(generator expressions)以及其他一些有趣的 Python 特性是怎么编译的;从字节码的层面来看