MDEV-20927 Duplicate key with auto increment
Apply the changes to InnoDB and XtraDB that had been inadvertently skipped in the merge commit ae476868a5394041a00e75a29c7d45917e8dfae8 That merge failure sabotaged part of MDEV-20127: >Revert a problematic auto_increment_increment 'fix' from 2014. >This involves replacing the MDEV-8827 fix and in 10.1, >removing some WSREP instrumentation. The code changes were re-merged manually by executing the following: # Get the parent of the problematic merge. git checkout ae476868a5394041a00e75a29c7d45917e8dfae8^ # Perform the merge again. git merge ae476868a5394041a00e75a29c7d45917e8dfae8^2 # Get the conflict resolution from that merge. git checkout ae476868a5394041a00e75a29c7d45917e8dfae8 . # Note: Any changes to these files were removed (empty diff)! git diff HEAD storage/{innobase,xtradb}/handler/ha_innodb.cc # Apply the code changes: git diff cf40393471b10ca68cc1d2804c22ab9203900978^2..MERGE_HEAD \ storage/{innobase,xtradb}/handler/ha_innodb.cc| patch -p1
This commit is contained in:
parent
b8eff8bce4
commit
d1e6b0bcff
@ -148,7 +148,7 @@ t1 CREATE TABLE `t1` (
|
|||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY `id` (`id`,`a`)
|
KEY `id` (`id`,`a`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=75 DEFAULT CHARSET=latin1
|
) ENGINE=InnoDB AUTO_INCREMENT=70 DEFAULT CHARSET=latin1
|
||||||
INSERT INTO t1 SET a=123;
|
INSERT INTO t1 SET a=123;
|
||||||
INSERT INTO t1 VALUES(-123,-45);
|
INSERT INTO t1 VALUES(-123,-45);
|
||||||
ALTER TABLE t1 AUTO_INCREMENT = 75;
|
ALTER TABLE t1 AUTO_INCREMENT = 75;
|
||||||
@ -161,8 +161,8 @@ a id
|
|||||||
123 55
|
123 55
|
||||||
347 60
|
347 60
|
||||||
33101 65
|
33101 65
|
||||||
|
123 70
|
||||||
123 75
|
123 75
|
||||||
123 80
|
|
||||||
SHOW CREATE TABLE t1;
|
SHOW CREATE TABLE t1;
|
||||||
Table Create Table
|
Table Create Table
|
||||||
t1 CREATE TABLE `t1` (
|
t1 CREATE TABLE `t1` (
|
||||||
@ -170,5 +170,5 @@ t1 CREATE TABLE `t1` (
|
|||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY `id` (`id`,`a`)
|
KEY `id` (`id`,`a`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=85 DEFAULT CHARSET=latin1
|
) ENGINE=InnoDB AUTO_INCREMENT=80 DEFAULT CHARSET=latin1
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
@ -567,7 +567,7 @@ Variable_name Value
|
|||||||
auto_increment_increment 65535
|
auto_increment_increment 65535
|
||||||
auto_increment_offset 65535
|
auto_increment_offset 65535
|
||||||
INSERT INTO t1 VALUES (NULL),(NULL);
|
INSERT INTO t1 VALUES (NULL),(NULL);
|
||||||
ERROR HY000: Failed to read auto-increment value from storage engine
|
ERROR 22003: Out of range value for column 'c1' at row 1
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
c1
|
c1
|
||||||
1
|
1
|
||||||
@ -674,7 +674,7 @@ SELECT a,b FROM t;
|
|||||||
a b
|
a b
|
||||||
1 S1
|
1 S1
|
||||||
3 S2
|
3 S2
|
||||||
4 S2
|
5 S2
|
||||||
# Client 1: Insert a record with auto_increment_increment=1
|
# Client 1: Insert a record with auto_increment_increment=1
|
||||||
SET SESSION auto_increment_increment=1;
|
SET SESSION auto_increment_increment=1;
|
||||||
SHOW CREATE TABLE t;
|
SHOW CREATE TABLE t;
|
||||||
@ -683,14 +683,14 @@ t CREATE TABLE `t` (
|
|||||||
`a` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
`a` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
`b` varchar(200) DEFAULT NULL,
|
`b` varchar(200) DEFAULT NULL,
|
||||||
PRIMARY KEY (`a`)
|
PRIMARY KEY (`a`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1
|
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1
|
||||||
INSERT INTO t(b) VALUES('S1');
|
INSERT INTO t(b) VALUES('S1');
|
||||||
SELECT a,b FROM t;
|
SELECT a,b FROM t;
|
||||||
a b
|
a b
|
||||||
1 S1
|
1 S1
|
||||||
3 S2
|
3 S2
|
||||||
4 S2
|
5 S2
|
||||||
5 S1
|
6 S1
|
||||||
DROP TABLE t;
|
DROP TABLE t;
|
||||||
# Autoincrement behaviour with mixed insert.
|
# Autoincrement behaviour with mixed insert.
|
||||||
CREATE TABLE t(
|
CREATE TABLE t(
|
||||||
@ -728,22 +728,22 @@ t CREATE TABLE `t` (
|
|||||||
`a` tinyint(4) NOT NULL AUTO_INCREMENT,
|
`a` tinyint(4) NOT NULL AUTO_INCREMENT,
|
||||||
`b` varchar(200) DEFAULT NULL,
|
`b` varchar(200) DEFAULT NULL,
|
||||||
PRIMARY KEY (`a`)
|
PRIMARY KEY (`a`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=latin1
|
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=latin1
|
||||||
INSERT INTO t(b) VALUES('S4');
|
INSERT INTO t(b) VALUES('S4');
|
||||||
SELECT * FROM t;
|
SELECT * FROM t;
|
||||||
a b
|
a b
|
||||||
1 S0
|
1 S0
|
||||||
11 S1
|
11 S1
|
||||||
22 S3
|
|
||||||
23 S4
|
|
||||||
28 S2
|
28 S2
|
||||||
|
31 S3
|
||||||
|
32 S4
|
||||||
SHOW CREATE TABLE t;
|
SHOW CREATE TABLE t;
|
||||||
Table Create Table
|
Table Create Table
|
||||||
t CREATE TABLE `t` (
|
t CREATE TABLE `t` (
|
||||||
`a` tinyint(4) NOT NULL AUTO_INCREMENT,
|
`a` tinyint(4) NOT NULL AUTO_INCREMENT,
|
||||||
`b` varchar(200) DEFAULT NULL,
|
`b` varchar(200) DEFAULT NULL,
|
||||||
PRIMARY KEY (`a`)
|
PRIMARY KEY (`a`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=latin1
|
) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=latin1
|
||||||
DROP TABLE t;
|
DROP TABLE t;
|
||||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=5;
|
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=5;
|
||||||
DROP TABLE IF EXISTS t1;
|
DROP TABLE IF EXISTS t1;
|
||||||
@ -784,7 +784,7 @@ t2 CREATE TABLE `t2` (
|
|||||||
`n` int(10) unsigned NOT NULL,
|
`n` int(10) unsigned NOT NULL,
|
||||||
`o` enum('FALSE','TRUE') DEFAULT NULL,
|
`o` enum('FALSE','TRUE') DEFAULT NULL,
|
||||||
PRIMARY KEY (`m`)
|
PRIMARY KEY (`m`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=latin1
|
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=latin1
|
||||||
INSERT INTO t1 (b,c) SELECT n,o FROM t2 ;
|
INSERT INTO t1 (b,c) SELECT n,o FROM t2 ;
|
||||||
SHOW CREATE TABLE t1;
|
SHOW CREATE TABLE t1;
|
||||||
Table Create Table
|
Table Create Table
|
||||||
@ -1464,13 +1464,13 @@ SELECT * FROM t;
|
|||||||
i
|
i
|
||||||
1
|
1
|
||||||
301
|
301
|
||||||
351
|
601
|
||||||
SHOW CREATE TABLE t;
|
SHOW CREATE TABLE t;
|
||||||
Table Create Table
|
Table Create Table
|
||||||
t CREATE TABLE `t` (
|
t CREATE TABLE `t` (
|
||||||
`i` int(11) NOT NULL AUTO_INCREMENT,
|
`i` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
KEY `i` (`i`)
|
KEY `i` (`i`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=401 DEFAULT CHARSET=latin1
|
) ENGINE=InnoDB AUTO_INCREMENT=651 DEFAULT CHARSET=latin1
|
||||||
DROP TABLE t;
|
DROP TABLE t;
|
||||||
#
|
#
|
||||||
# MDEV-14008 Assertion failing: `!is_set() || (m_status == DA_OK_BULK && is_bulk_op())
|
# MDEV-14008 Assertion failing: `!is_set() || (m_status == DA_OK_BULK && is_bulk_op())
|
||||||
|
@ -349,7 +349,7 @@ INSERT INTO t1 VALUES (18446744073709551610); #-- 2^64 - 2
|
|||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1152921504606846976, @@SESSION.AUTO_INCREMENT_OFFSET=1152921504606846976;
|
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1152921504606846976, @@SESSION.AUTO_INCREMENT_OFFSET=1152921504606846976;
|
||||||
SHOW VARIABLES LIKE "auto_inc%";
|
SHOW VARIABLES LIKE "auto_inc%";
|
||||||
--error 1467
|
--error HA_ERR_AUTOINC_ERANGE
|
||||||
INSERT INTO t1 VALUES (NULL),(NULL);
|
INSERT INTO t1 VALUES (NULL),(NULL);
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
Copyright (c) 2008, 2009 Google Inc.
|
Copyright (c) 2008, 2009 Google Inc.
|
||||||
Copyright (c) 2009, Percona Inc.
|
Copyright (c) 2009, Percona Inc.
|
||||||
Copyright (c) 2012, Facebook Inc.
|
Copyright (c) 2012, Facebook Inc.
|
||||||
@ -2588,11 +2588,10 @@ innobase_next_autoinc(
|
|||||||
if (next_value == 0) {
|
if (next_value == 0) {
|
||||||
ulonglong next;
|
ulonglong next;
|
||||||
|
|
||||||
if (current >= offset) {
|
if (current > offset) {
|
||||||
next = (current - offset) / step;
|
next = (current - offset) / step;
|
||||||
} else {
|
} else {
|
||||||
next = 0;
|
next = (offset - current) / step;
|
||||||
block -= step;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_a(max_value > next);
|
ut_a(max_value > next);
|
||||||
@ -16035,6 +16034,37 @@ ha_innobase::get_auto_increment(
|
|||||||
ut_ad(autoinc > 0);
|
ut_ad(autoinc > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** The following logic is needed to avoid duplicate key error
|
||||||
|
for autoincrement column.
|
||||||
|
|
||||||
|
(1) InnoDB gives the current autoincrement value with respect
|
||||||
|
to increment and offset value.
|
||||||
|
|
||||||
|
(2) Basically it does compute_next_insert_id() logic inside InnoDB
|
||||||
|
to avoid the current auto increment value changed by handler layer.
|
||||||
|
|
||||||
|
(3) It is restricted only for insert operations. */
|
||||||
|
|
||||||
|
if (increment > 1 && thd_sql_command(user_thd) != SQLCOM_ALTER_TABLE
|
||||||
|
&& autoinc < col_max_value) {
|
||||||
|
|
||||||
|
ulonglong prev_auto_inc = autoinc;
|
||||||
|
|
||||||
|
autoinc = ((autoinc - 1) + increment - offset)/ increment;
|
||||||
|
|
||||||
|
autoinc = autoinc * increment + offset;
|
||||||
|
|
||||||
|
/* If autoinc exceeds the col_max_value then reset
|
||||||
|
to old autoinc value. Because in case of non-strict
|
||||||
|
sql mode, boundary value is not considered as error. */
|
||||||
|
|
||||||
|
if (autoinc >= col_max_value) {
|
||||||
|
autoinc = prev_auto_inc;
|
||||||
|
}
|
||||||
|
|
||||||
|
ut_ad(autoinc > 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Called for the first time ? */
|
/* Called for the first time ? */
|
||||||
if (trx->n_autoinc_rows == 0) {
|
if (trx->n_autoinc_rows == 0) {
|
||||||
|
|
||||||
@ -16072,26 +16102,6 @@ ha_innobase::get_auto_increment(
|
|||||||
|
|
||||||
current = *first_value;
|
current = *first_value;
|
||||||
|
|
||||||
if (prebuilt->autoinc_increment != increment) {
|
|
||||||
|
|
||||||
WSREP_DEBUG("autoinc decrease: %llu -> %llu\n"
|
|
||||||
"THD: %ld, current: %llu, autoinc: %llu",
|
|
||||||
prebuilt->autoinc_increment,
|
|
||||||
increment,
|
|
||||||
thd_get_thread_id(ha_thd()),
|
|
||||||
current, autoinc);
|
|
||||||
if (!wsrep_on(ha_thd()))
|
|
||||||
{
|
|
||||||
current = autoinc - prebuilt->autoinc_increment;
|
|
||||||
current = innobase_next_autoinc(
|
|
||||||
current, 1, increment, offset, col_max_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
dict_table_autoinc_initialize(prebuilt->table, current);
|
|
||||||
|
|
||||||
*first_value = current;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Compute the last value in the interval */
|
/* Compute the last value in the interval */
|
||||||
next_value = innobase_next_autoinc(
|
next_value = innobase_next_autoinc(
|
||||||
current, *nb_reserved_values, increment, offset,
|
current, *nb_reserved_values, increment, offset,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
Copyright (c) 2013, 2018, MariaDB Corporation.
|
Copyright (c) 2013, 2018, MariaDB Corporation.
|
||||||
Copyright (c) 2008, 2009 Google Inc.
|
Copyright (c) 2008, 2009 Google Inc.
|
||||||
Copyright (c) 2009, Percona Inc.
|
Copyright (c) 2009, Percona Inc.
|
||||||
@ -2899,11 +2899,10 @@ innobase_next_autoinc(
|
|||||||
if (next_value == 0) {
|
if (next_value == 0) {
|
||||||
ulonglong next;
|
ulonglong next;
|
||||||
|
|
||||||
if (current >= offset) {
|
if (current > offset) {
|
||||||
next = (current - offset) / step;
|
next = (current - offset) / step;
|
||||||
} else {
|
} else {
|
||||||
next = 0;
|
next = (offset - current) / step;
|
||||||
block -= step;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_a(max_value > next);
|
ut_a(max_value > next);
|
||||||
@ -16673,6 +16672,37 @@ ha_innobase::get_auto_increment(
|
|||||||
ut_ad(autoinc > 0);
|
ut_ad(autoinc > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** The following logic is needed to avoid duplicate key error
|
||||||
|
for autoincrement column.
|
||||||
|
|
||||||
|
(1) InnoDB gives the current autoincrement value with respect
|
||||||
|
to increment and offset value.
|
||||||
|
|
||||||
|
(2) Basically it does compute_next_insert_id() logic inside InnoDB
|
||||||
|
to avoid the current auto increment value changed by handler layer.
|
||||||
|
|
||||||
|
(3) It is restricted only for insert operations. */
|
||||||
|
|
||||||
|
if (increment > 1 && thd_sql_command(user_thd) != SQLCOM_ALTER_TABLE
|
||||||
|
&& autoinc < col_max_value) {
|
||||||
|
|
||||||
|
ulonglong prev_auto_inc = autoinc;
|
||||||
|
|
||||||
|
autoinc = ((autoinc - 1) + increment - offset)/ increment;
|
||||||
|
|
||||||
|
autoinc = autoinc * increment + offset;
|
||||||
|
|
||||||
|
/* If autoinc exceeds the col_max_value then reset
|
||||||
|
to old autoinc value. Because in case of non-strict
|
||||||
|
sql mode, boundary value is not considered as error. */
|
||||||
|
|
||||||
|
if (autoinc >= col_max_value) {
|
||||||
|
autoinc = prev_auto_inc;
|
||||||
|
}
|
||||||
|
|
||||||
|
ut_ad(autoinc > 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Called for the first time ? */
|
/* Called for the first time ? */
|
||||||
if (trx->n_autoinc_rows == 0) {
|
if (trx->n_autoinc_rows == 0) {
|
||||||
|
|
||||||
@ -16710,26 +16740,6 @@ ha_innobase::get_auto_increment(
|
|||||||
|
|
||||||
current = *first_value;
|
current = *first_value;
|
||||||
|
|
||||||
if (prebuilt->autoinc_increment != increment) {
|
|
||||||
|
|
||||||
WSREP_DEBUG("autoinc decrease: %llu -> %llu\n"
|
|
||||||
"THD: %ld, current: %llu, autoinc: %llu",
|
|
||||||
prebuilt->autoinc_increment,
|
|
||||||
increment,
|
|
||||||
thd_get_thread_id(ha_thd()),
|
|
||||||
current, autoinc);
|
|
||||||
if (!wsrep_on(ha_thd()))
|
|
||||||
{
|
|
||||||
current = autoinc - prebuilt->autoinc_increment;
|
|
||||||
current = innobase_next_autoinc(
|
|
||||||
current, 1, increment, offset, col_max_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
dict_table_autoinc_initialize(prebuilt->table, current);
|
|
||||||
|
|
||||||
*first_value = current;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Compute the last value in the interval */
|
/* Compute the last value in the interval */
|
||||||
next_value = innobase_next_autoinc(
|
next_value = innobase_next_autoinc(
|
||||||
current, *nb_reserved_values, increment, offset,
|
current, *nb_reserved_values, increment, offset,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user