Commit 90436a09 authored by Sunny Bains's avatar Sunny Bains

Bug #13817703 - auto_increment_offset != 1 + innodb_autoinc_lock_mode=1 => bulk inserts fail

        
Fix the calculation of the next autoinc value when offset > 1. Some of the
results have changed due to the changes in the allocation calculation. The
new calculation will result in slightly bigger gaps for bulk inserts.
  
rb://866 Approved by Jimmy Yang.
Backported from mysql-trunk (5.6)
parent ea40710d
...@@ -648,7 +648,7 @@ t2 CREATE TABLE `t2` ( ...@@ -648,7 +648,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=15 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
...@@ -657,7 +657,7 @@ t1 CREATE TABLE `t1` ( ...@@ -657,7 +657,7 @@ t1 CREATE TABLE `t1` (
`b` int(10) unsigned NOT NULL, `b` int(10) unsigned NOT NULL,
`c` enum('FALSE','TRUE') DEFAULT NULL, `c` enum('FALSE','TRUE') DEFAULT NULL,
PRIMARY KEY (`a`) PRIMARY KEY (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=latin1 ) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=latin1
INSERT INTO t1 (b,c) SELECT n,o FROM t2 ; INSERT INTO t1 (b,c) SELECT n,o FROM t2 ;
SELECT * FROM t1; SELECT * FROM t1;
a b c a b c
...@@ -671,16 +671,16 @@ a b c ...@@ -671,16 +671,16 @@ a b c
8 4 FALSE 8 4 FALSE
9 5 TRUE 9 5 TRUE
10 5 FALSE 10 5 FALSE
13 1 TRUE 16 1 TRUE
14 1 FALSE 17 1 FALSE
15 2 TRUE 18 2 TRUE
16 2 FALSE 19 2 FALSE
17 3 TRUE 20 3 TRUE
18 3 FALSE 21 3 FALSE
19 4 TRUE 22 4 TRUE
20 4 FALSE 23 4 FALSE
21 5 TRUE 24 5 TRUE
22 5 FALSE 25 5 FALSE
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
...@@ -688,7 +688,7 @@ t1 CREATE TABLE `t1` ( ...@@ -688,7 +688,7 @@ t1 CREATE TABLE `t1` (
`b` int(10) unsigned NOT NULL, `b` int(10) unsigned NOT NULL,
`c` enum('FALSE','TRUE') DEFAULT NULL, `c` enum('FALSE','TRUE') DEFAULT NULL,
PRIMARY KEY (`a`) PRIMARY KEY (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=latin1 ) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=latin1
INSERT INTO t1 (b,c) SELECT n,o FROM t2 WHERE o = 'false'; INSERT INTO t1 (b,c) SELECT n,o FROM t2 WHERE o = 'false';
SELECT * FROM t1; SELECT * FROM t1;
a b c a b c
...@@ -702,21 +702,21 @@ a b c ...@@ -702,21 +702,21 @@ a b c
8 4 FALSE 8 4 FALSE
9 5 TRUE 9 5 TRUE
10 5 FALSE 10 5 FALSE
13 1 TRUE 16 1 TRUE
14 1 FALSE 17 1 FALSE
15 2 TRUE 18 2 TRUE
16 2 FALSE 19 2 FALSE
17 3 TRUE 20 3 TRUE
18 3 FALSE 21 3 FALSE
19 4 TRUE 22 4 TRUE
20 4 FALSE 23 4 FALSE
21 5 TRUE 24 5 TRUE
22 5 FALSE 25 5 FALSE
23 1 FALSE 31 1 FALSE
24 2 FALSE 32 2 FALSE
25 3 FALSE 33 3 FALSE
26 4 FALSE 34 4 FALSE
27 5 FALSE 35 5 FALSE
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
...@@ -724,7 +724,7 @@ t1 CREATE TABLE `t1` ( ...@@ -724,7 +724,7 @@ t1 CREATE TABLE `t1` (
`b` int(10) unsigned NOT NULL, `b` int(10) unsigned NOT NULL,
`c` enum('FALSE','TRUE') DEFAULT NULL, `c` enum('FALSE','TRUE') DEFAULT NULL,
PRIMARY KEY (`a`) PRIMARY KEY (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=latin1 ) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=latin1
INSERT INTO t1 (b,c) SELECT n,o FROM t2 WHERE o = 'false'; INSERT INTO t1 (b,c) SELECT n,o FROM t2 WHERE o = 'false';
SELECT * FROM t1; SELECT * FROM t1;
a b c a b c
...@@ -738,26 +738,26 @@ a b c ...@@ -738,26 +738,26 @@ a b c
8 4 FALSE 8 4 FALSE
9 5 TRUE 9 5 TRUE
10 5 FALSE 10 5 FALSE
13 1 TRUE 16 1 TRUE
14 1 FALSE 17 1 FALSE
15 2 TRUE 18 2 TRUE
16 2 FALSE 19 2 FALSE
17 3 TRUE 20 3 TRUE
18 3 FALSE 21 3 FALSE
19 4 TRUE 22 4 TRUE
20 4 FALSE 23 4 FALSE
21 5 TRUE 24 5 TRUE
22 5 FALSE 25 5 FALSE
23 1 FALSE 31 1 FALSE
24 2 FALSE 32 2 FALSE
25 3 FALSE 33 3 FALSE
26 4 FALSE 34 4 FALSE
27 5 FALSE 35 5 FALSE
30 1 FALSE 38 1 FALSE
31 2 FALSE 39 2 FALSE
32 3 FALSE 40 3 FALSE
33 4 FALSE 41 4 FALSE
34 5 FALSE 42 5 FALSE
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
...@@ -765,7 +765,7 @@ t1 CREATE TABLE `t1` ( ...@@ -765,7 +765,7 @@ t1 CREATE TABLE `t1` (
`b` int(10) unsigned NOT NULL, `b` int(10) unsigned NOT NULL,
`c` enum('FALSE','TRUE') DEFAULT NULL, `c` enum('FALSE','TRUE') DEFAULT NULL,
PRIMARY KEY (`a`) PRIMARY KEY (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=37 DEFAULT CHARSET=latin1 ) ENGINE=InnoDB AUTO_INCREMENT=45 DEFAULT CHARSET=latin1
INSERT INTO t1 (b,c) SELECT n,o FROM t2 WHERE o = 'false'; INSERT INTO t1 (b,c) SELECT n,o FROM t2 WHERE o = 'false';
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
...@@ -774,7 +774,7 @@ t1 CREATE TABLE `t1` ( ...@@ -774,7 +774,7 @@ t1 CREATE TABLE `t1` (
`b` int(10) unsigned NOT NULL, `b` int(10) unsigned NOT NULL,
`c` enum('FALSE','TRUE') DEFAULT NULL, `c` enum('FALSE','TRUE') DEFAULT NULL,
PRIMARY KEY (`a`) PRIMARY KEY (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=44 DEFAULT CHARSET=latin1 ) ENGINE=InnoDB AUTO_INCREMENT=52 DEFAULT CHARSET=latin1
INSERT INTO t1 (b,c) SELECT n,o FROM t2 WHERE o = 'false'; INSERT INTO t1 (b,c) SELECT n,o FROM t2 WHERE o = 'false';
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
...@@ -783,7 +783,7 @@ t1 CREATE TABLE `t1` ( ...@@ -783,7 +783,7 @@ t1 CREATE TABLE `t1` (
`b` int(10) unsigned NOT NULL, `b` int(10) unsigned NOT NULL,
`c` enum('FALSE','TRUE') DEFAULT NULL, `c` enum('FALSE','TRUE') DEFAULT NULL,
PRIMARY KEY (`a`) PRIMARY KEY (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=51 DEFAULT CHARSET=latin1 ) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=latin1
INSERT INTO t1 (b,c) SELECT n,o FROM t2 WHERE o = 'false'; INSERT INTO t1 (b,c) SELECT n,o FROM t2 WHERE o = 'false';
SELECT * FROM t1; SELECT * FROM t1;
a b c a b c
...@@ -797,41 +797,41 @@ a b c ...@@ -797,41 +797,41 @@ a b c
8 4 FALSE 8 4 FALSE
9 5 TRUE 9 5 TRUE
10 5 FALSE 10 5 FALSE
13 1 TRUE 16 1 TRUE
14 1 FALSE 17 1 FALSE
15 2 TRUE 18 2 TRUE
16 2 FALSE 19 2 FALSE
17 3 TRUE 20 3 TRUE
18 3 FALSE 21 3 FALSE
19 4 TRUE 22 4 TRUE
20 4 FALSE 23 4 FALSE
21 5 TRUE 24 5 TRUE
22 5 FALSE 25 5 FALSE
23 1 FALSE 31 1 FALSE
24 2 FALSE 32 2 FALSE
25 3 FALSE 33 3 FALSE
26 4 FALSE 34 4 FALSE
27 5 FALSE 35 5 FALSE
30 1 FALSE 38 1 FALSE
31 2 FALSE 39 2 FALSE
32 3 FALSE 40 3 FALSE
33 4 FALSE 41 4 FALSE
34 5 FALSE 42 5 FALSE
37 1 FALSE 45 1 FALSE
38 2 FALSE 46 2 FALSE
39 3 FALSE 47 3 FALSE
40 4 FALSE 48 4 FALSE
41 5 FALSE 49 5 FALSE
44 1 FALSE 52 1 FALSE
45 2 FALSE 53 2 FALSE
46 3 FALSE 54 3 FALSE
47 4 FALSE 55 4 FALSE
48 5 FALSE 56 5 FALSE
51 1 FALSE 59 1 FALSE
52 2 FALSE 60 2 FALSE
53 3 FALSE 61 3 FALSE
54 4 FALSE 62 4 FALSE
55 5 FALSE 63 5 FALSE
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
...@@ -839,7 +839,7 @@ t1 CREATE TABLE `t1` ( ...@@ -839,7 +839,7 @@ t1 CREATE TABLE `t1` (
`b` int(10) unsigned NOT NULL, `b` int(10) unsigned NOT NULL,
`c` enum('FALSE','TRUE') DEFAULT NULL, `c` enum('FALSE','TRUE') DEFAULT NULL,
PRIMARY KEY (`a`) PRIMARY KEY (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=58 DEFAULT CHARSET=latin1 ) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=latin1
DROP TABLE t1; DROP TABLE t1;
DROP TABLE t2; DROP TABLE t2;
DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t1;
...@@ -1251,3 +1251,21 @@ t1 CREATE TABLE `t1` ( ...@@ -1251,3 +1251,21 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`c1`) PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=18446744073709551615 DEFAULT CHARSET=latin1 ) ENGINE=InnoDB AUTO_INCREMENT=18446744073709551615 DEFAULT CHARSET=latin1
DROP TABLE t1; DROP TABLE t1;
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=256;
SHOW VARIABLES LIKE "%auto_inc%";
Variable_name Value
auto_increment_increment 1
auto_increment_offset 256
CREATE TABLE t1 (c1 TINYINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1, NULL);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` tinyint(4) NOT NULL AUTO_INCREMENT,
`c2` varchar(10) DEFAULT NULL,
PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1
SELECT * FROM t1;
c1 c2
1 NULL
DROP TABLE t1;
...@@ -637,3 +637,14 @@ INSERT INTO t1 VALUES (18446744073709551615); ...@@ -637,3 +637,14 @@ INSERT INTO t1 VALUES (18446744073709551615);
-- source include/restart_mysqld.inc -- source include/restart_mysqld.inc
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
DROP TABLE t1; DROP TABLE t1;
# Check if we handl offset > column max value properly
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=256;
SHOW VARIABLES LIKE "%auto_inc%";
# TINYINT
CREATE TABLE t1 (c1 TINYINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1, NULL);
SHOW CREATE TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
...@@ -1447,70 +1447,87 @@ values we want to reserve for multi-value inserts e.g., ...@@ -1447,70 +1447,87 @@ values we want to reserve for multi-value inserts e.g.,
INSERT INTO T VALUES(), (), (); INSERT INTO T VALUES(), (), ();
innobase_next_autoinc() will be called with increment set to innobase_next_autoinc() will be called with increment set to 3 where
n * 3 where autoinc_lock_mode != TRADITIONAL because we want autoinc_lock_mode != TRADITIONAL because we want to reserve 3 values for
to reserve 3 values for the multi-value INSERT above. the multi-value INSERT above.
@return the next value */ @return the next value */
static static
ulonglong ulonglong
innobase_next_autoinc( innobase_next_autoinc(
/*==================*/ /*==================*/
ulonglong current, /*!< in: Current value */ ulonglong current, /*!< in: Current value */
ulonglong increment, /*!< in: increment current by */ ulonglong need, /*!< in: count of values needed */
ulonglong step, /*!< in: AUTOINC increment step */
ulonglong offset, /*!< in: AUTOINC offset */ ulonglong offset, /*!< in: AUTOINC offset */
ulonglong max_value) /*!< in: max value for type */ ulonglong max_value) /*!< in: max value for type */
{ {
ulonglong next_value; ulonglong next_value;
ulonglong block = need * step;
/* Should never be 0. */ /* Should never be 0. */
ut_a(increment > 0); ut_a(need > 0);
ut_a(block > 0);
ut_a(max_value > 0);
/* Current value should never be greater than the maximum. */
ut_a(current <= max_value);
/* According to MySQL documentation, if the offset is greater than /* According to MySQL documentation, if the offset is greater than
the increment then the offset is ignored. */ the step then the offset is ignored. */
if (offset > increment) { if (offset > block) {
offset = 0; offset = 0;
} }
if (max_value <= current) { /* Check for overflow. */
if (block >= max_value
|| offset > max_value
|| current == max_value
|| max_value - offset <= offset) {
next_value = max_value; next_value = max_value;
} else if (offset <= 1) { } else {
/* Offset 0 and 1 are the same, because there must be at ut_a(max_value > current);
least one node in the system. */
if (max_value - current <= increment) { ulonglong free = max_value - current;
if (free < offset || free - offset <= block) {
next_value = max_value; next_value = max_value;
} else { } else {
next_value = current + increment; next_value = 0;
}
} }
} else if (max_value > current) {
if (next_value == 0) {
ulonglong next;
if (current > offset) { if (current > offset) {
next_value = ((current - offset) / increment) + 1; next = (current - offset) / step;
} else { } else {
next_value = ((offset - current) / increment) + 1; next = (offset - current) / step;
} }
ut_a(increment > 0); ut_a(max_value > next);
ut_a(next_value > 0); next_value = next * step;
/* Check for multiplication overflow. */ /* Check for multiplication overflow. */
if (increment > (max_value / next_value)) { ut_a(next_value >= next);
ut_a(max_value > next_value);
next_value = max_value; /* Check for overflow */
} else { if (max_value - next_value >= block) {
next_value *= increment;
ut_a(max_value >= next_value); next_value += block;
/* Check for overflow. */ if (max_value - next_value >= offset) {
if (max_value - next_value <= offset) {
next_value = max_value;
} else {
next_value += offset; next_value += offset;
} } else {
next_value = max_value;
} }
} else { } else {
next_value = max_value; next_value = max_value;
} }
}
ut_a(next_value != 0);
ut_a(next_value <= max_value); ut_a(next_value <= max_value);
return(next_value); return(next_value);
...@@ -3746,7 +3763,7 @@ ha_innobase::innobase_initialize_autoinc() ...@@ -3746,7 +3763,7 @@ ha_innobase::innobase_initialize_autoinc()
nor the offset, so use a default increment of 1. */ nor the offset, so use a default increment of 1. */
auto_inc = innobase_next_autoinc( auto_inc = innobase_next_autoinc(
read_auto_inc, 1, 1, col_max_value); read_auto_inc, 1, 1, 0, col_max_value);
break; break;
} }
...@@ -5246,15 +5263,16 @@ set_max_autoinc: ...@@ -5246,15 +5263,16 @@ set_max_autoinc:
if (auto_inc <= col_max_value) { if (auto_inc <= col_max_value) {
ut_a(prebuilt->autoinc_increment > 0); ut_a(prebuilt->autoinc_increment > 0);
ulonglong need;
ulonglong offset; ulonglong offset;
ulonglong increment;
offset = prebuilt->autoinc_offset; offset = prebuilt->autoinc_offset;
need = prebuilt->autoinc_increment; increment = prebuilt->autoinc_increment;
auto_inc = innobase_next_autoinc( auto_inc = innobase_next_autoinc(
auto_inc, auto_inc,
need, offset, col_max_value); 1, increment, offset,
col_max_value);
err = innobase_set_max_autoinc( err = innobase_set_max_autoinc(
auto_inc); auto_inc);
...@@ -5522,14 +5540,14 @@ ha_innobase::update_row( ...@@ -5522,14 +5540,14 @@ ha_innobase::update_row(
if (auto_inc <= col_max_value && auto_inc != 0) { if (auto_inc <= col_max_value && auto_inc != 0) {
ulonglong need;
ulonglong offset; ulonglong offset;
ulonglong increment;
offset = prebuilt->autoinc_offset; offset = prebuilt->autoinc_offset;
need = prebuilt->autoinc_increment; increment = prebuilt->autoinc_increment;
auto_inc = innobase_next_autoinc( auto_inc = innobase_next_autoinc(
auto_inc, need, offset, col_max_value); auto_inc, 1, increment, offset, col_max_value);
error = innobase_set_max_autoinc(auto_inc); error = innobase_set_max_autoinc(auto_inc);
} }
...@@ -10139,16 +10157,15 @@ ha_innobase::get_auto_increment( ...@@ -10139,16 +10157,15 @@ ha_innobase::get_auto_increment(
/* With old style AUTOINC locking we only update the table's /* With old style AUTOINC locking we only update the table's
AUTOINC counter after attempting to insert the row. */ AUTOINC counter after attempting to insert the row. */
if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) { if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
ulonglong need;
ulonglong current; ulonglong current;
ulonglong next_value; ulonglong next_value;
current = *first_value > col_max_value ? autoinc : *first_value; current = *first_value > col_max_value ? autoinc : *first_value;
need = *nb_reserved_values * increment;
/* 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, need, offset, col_max_value); current, *nb_reserved_values, increment, offset,
col_max_value);
prebuilt->autoinc_last_value = next_value; prebuilt->autoinc_last_value = next_value;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment