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,
|
||||
PRIMARY KEY (`id`),
|
||||
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 VALUES(-123,-45);
|
||||
ALTER TABLE t1 AUTO_INCREMENT = 75;
|
||||
@ -161,8 +161,8 @@ a id
|
||||
123 55
|
||||
347 60
|
||||
33101 65
|
||||
123 70
|
||||
123 75
|
||||
123 80
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
@ -170,5 +170,5 @@ t1 CREATE TABLE `t1` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `id` (`id`,`a`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=85 DEFAULT CHARSET=latin1
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=80 DEFAULT CHARSET=latin1
|
||||
DROP TABLE t1;
|
||||
|
@ -567,7 +567,7 @@ Variable_name Value
|
||||
auto_increment_increment 65535
|
||||
auto_increment_offset 65535
|
||||
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;
|
||||
c1
|
||||
1
|
||||
@ -674,7 +674,7 @@ SELECT a,b FROM t;
|
||||
a b
|
||||
1 S1
|
||||
3 S2
|
||||
4 S2
|
||||
5 S2
|
||||
# Client 1: Insert a record with auto_increment_increment=1
|
||||
SET SESSION auto_increment_increment=1;
|
||||
SHOW CREATE TABLE t;
|
||||
@ -683,14 +683,14 @@ t CREATE TABLE `t` (
|
||||
`a` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`b` varchar(200) DEFAULT NULL,
|
||||
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');
|
||||
SELECT a,b FROM t;
|
||||
a b
|
||||
1 S1
|
||||
3 S2
|
||||
4 S2
|
||||
5 S1
|
||||
5 S2
|
||||
6 S1
|
||||
DROP TABLE t;
|
||||
# Autoincrement behaviour with mixed insert.
|
||||
CREATE TABLE t(
|
||||
@ -728,22 +728,22 @@ t CREATE TABLE `t` (
|
||||
`a` tinyint(4) NOT NULL AUTO_INCREMENT,
|
||||
`b` varchar(200) DEFAULT NULL,
|
||||
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');
|
||||
SELECT * FROM t;
|
||||
a b
|
||||
1 S0
|
||||
11 S1
|
||||
22 S3
|
||||
23 S4
|
||||
28 S2
|
||||
31 S3
|
||||
32 S4
|
||||
SHOW CREATE TABLE t;
|
||||
Table Create Table
|
||||
t CREATE TABLE `t` (
|
||||
`a` tinyint(4) NOT NULL AUTO_INCREMENT,
|
||||
`b` varchar(200) DEFAULT NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=latin1
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=latin1
|
||||
DROP TABLE t;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=5;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
@ -784,7 +784,7 @@ t2 CREATE TABLE `t2` (
|
||||
`n` int(10) unsigned NOT NULL,
|
||||
`o` enum('FALSE','TRUE') DEFAULT NULL,
|
||||
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 ;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
@ -1464,13 +1464,13 @@ SELECT * FROM t;
|
||||
i
|
||||
1
|
||||
301
|
||||
351
|
||||
601
|
||||
SHOW CREATE TABLE t;
|
||||
Table Create Table
|
||||
t CREATE TABLE `t` (
|
||||
`i` int(11) NOT NULL AUTO_INCREMENT,
|
||||
KEY `i` (`i`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=401 DEFAULT CHARSET=latin1
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=651 DEFAULT CHARSET=latin1
|
||||
DROP TABLE t;
|
||||
#
|
||||
# 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;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1152921504606846976, @@SESSION.AUTO_INCREMENT_OFFSET=1152921504606846976;
|
||||
SHOW VARIABLES LIKE "auto_inc%";
|
||||
--error 1467
|
||||
--error HA_ERR_AUTOINC_ERANGE
|
||||
INSERT INTO t1 VALUES (NULL),(NULL);
|
||||
SELECT * FROM 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) 2009, Percona Inc.
|
||||
Copyright (c) 2012, Facebook Inc.
|
||||
@ -2588,11 +2588,10 @@ innobase_next_autoinc(
|
||||
if (next_value == 0) {
|
||||
ulonglong next;
|
||||
|
||||
if (current >= offset) {
|
||||
if (current > offset) {
|
||||
next = (current - offset) / step;
|
||||
} else {
|
||||
next = 0;
|
||||
block -= step;
|
||||
next = (offset - current) / step;
|
||||
}
|
||||
|
||||
ut_a(max_value > next);
|
||||
@ -16035,6 +16034,37 @@ ha_innobase::get_auto_increment(
|
||||
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 ? */
|
||||
if (trx->n_autoinc_rows == 0) {
|
||||
|
||||
@ -16072,26 +16102,6 @@ ha_innobase::get_auto_increment(
|
||||
|
||||
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 */
|
||||
next_value = innobase_next_autoinc(
|
||||
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) 2008, 2009 Google Inc.
|
||||
Copyright (c) 2009, Percona Inc.
|
||||
@ -2899,11 +2899,10 @@ innobase_next_autoinc(
|
||||
if (next_value == 0) {
|
||||
ulonglong next;
|
||||
|
||||
if (current >= offset) {
|
||||
if (current > offset) {
|
||||
next = (current - offset) / step;
|
||||
} else {
|
||||
next = 0;
|
||||
block -= step;
|
||||
next = (offset - current) / step;
|
||||
}
|
||||
|
||||
ut_a(max_value > next);
|
||||
@ -16673,6 +16672,37 @@ ha_innobase::get_auto_increment(
|
||||
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 ? */
|
||||
if (trx->n_autoinc_rows == 0) {
|
||||
|
||||
@ -16710,26 +16740,6 @@ ha_innobase::get_auto_increment(
|
||||
|
||||
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 */
|
||||
next_value = innobase_next_autoinc(
|
||||
current, *nb_reserved_values, increment, offset,
|
||||
|
Loading…
x
Reference in New Issue
Block a user