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

原创文章,转载请注明: 转载自Simple Life

本文链接地址: [MySQL Bug]bug#66301(Percona Bug#1035225)简析

Post Footer automatically generated by wp-posturl plugin for wordpress.


Comments

Leave a Reply

Your email address will not be published. Name and email are required


Current month ye@r day *