INSERT ... ON DUPLICATE KEY UPDATE + innodb_autoinc_lock_mode=1 is broken
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
MySQL Server |
Unknown
|
Unknown
|
|||
Percona Server moved to https://jira.percona.com/projects/PS |
Fix Released
|
High
|
Alexey Kopytov | ||
5.1 |
Fix Released
|
High
|
Alexey Kopytov | ||
5.5 |
Fix Released
|
High
|
Alexey Kopytov |
Bug Description
Concurrent INSERT ... ON DUPLICATE KEY UPDATE statements on a table with
an AUTO_INCREMENT column may result in spurious duplicate key errors
(and, as a result, lost data due to some rows being updated rather than
inserted) with the default value of innodb_
The problem only appears with concurrently executing INSERT ... ON
DUPLICATE KEY UPDATE statements and is time-sensitive. Consider the
following table:
CREATE TABLE t(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
k INT,
c CHAR(1),
UNIQUE KEY(k)) ENGINE=InnoDB;
and the following two statements:
INSERT INTO t(k) VALUES (1), (2), (3) ON DUPLICATE KEY UPDATE c='1'; /* (1) */
INSERT INTO t(k) VALUES (2), (4), (5) ON DUPLICATE KEY UPDATE c='2'; /* (2) */
When statements (1) and (2) are executed sequentially, table 't'
contains the following rows as a result:
id k c
1 1 NULL
2 2 2
3 3 NULL
4 4 NULL
5 5 NULL
(the non-NULL value of the 'c' column depends on the order of execution)
However, if both statements are executed concurrently, and statement (2)
starts and finishes while statement (1) execution is in progress, the
result of both statements may become as follows:
id k c
1 1 NULL
4 2 1
5 4 1
6 5 NULL
The attached .test file uses DEBUG_SYNC points to demonstrate that.
The workaround is to use innodb_
statements with the InnoDB AUTO-INC lock. For example, try running the test
case with --mysqld=
Naturally, this bug also breaks statement-based replication and results
in inconsistent slaves.
The root cause is that when the statements are executed concurrently in
such a way, InnoDB will correctly reserve non-overlapping AUTO_INCREMENT
intervals for each statement, but when the server encounters the first
duplicate key error on the secondary key in statement (1) and performs
an UPDATE, it also updates the internal AUTO_INCREMENT value to the one
corresponding to the row inserted by statement (2), even though it is
not specified explicitly in the UPDATE part. It will then proceed with
using AUTO_INCREMENT values for statement (1) from the range reserved
previously by statement (2), causing duplicate key errors on the
AUTO_INCREMENT column.
Related branches
- Laurynas Biveinis (community): Approve
-
Diff: 237 lines (+131/-2)6 files modifiedPercona-Server/mysql-test/r/percona_bug1035225.result (+32/-0)
Percona-Server/mysql-test/t/percona_bug1035225.test (+47/-0)
Percona-Server/sql/handler.cc (+2/-0)
Percona-Server/sql/sql_insert.cc (+44/-2)
Percona-Server/sql/sql_parse.cc (+1/-0)
Percona-Server/sql/table.h (+5/-0)
- Laurynas Biveinis (community): Approve
-
Diff: 224 lines (+129/-2)5 files modifiedPercona-Server/mysql-test/r/percona_bug1035225.result (+32/-0)
Percona-Server/mysql-test/t/percona_bug1035225.test (+47/-0)
Percona-Server/sql/sql_insert.cc (+44/-2)
Percona-Server/sql/sql_parse.cc (+1/-0)
Percona-Server/sql/table.h (+5/-0)
tags: | added: i25040 |
see bug 1582577