summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSunny Bains <Sunny.Bains@Oracle.Com>2012-03-29 18:02:08 +1100
committerSunny Bains <Sunny.Bains@Oracle.Com>2012-03-29 18:02:08 +1100
commitd1809a5c85bf76136aa7645c152e9f723fd4250b (patch)
tree195d41ba841264f685b0e26372213116fba55062
parent7553f9eefdcdf67d31caa2a64b826dd476b4c35e (diff)
downloadmariadb-git-d1809a5c85bf76136aa7645c152e9f723fd4250b.tar.gz
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)
-rw-r--r--mysql-test/suite/innodb/r/innodb-autoinc.result194
-rw-r--r--mysql-test/suite/innodb/t/innodb-autoinc.test11
-rw-r--r--storage/innobase/handler/ha_innodb.cc97
3 files changed, 174 insertions, 128 deletions
diff --git a/mysql-test/suite/innodb/r/innodb-autoinc.result b/mysql-test/suite/innodb/r/innodb-autoinc.result
index 0c8d16f27fb..9eb89bead74 100644
--- a/mysql-test/suite/innodb/r/innodb-autoinc.result
+++ b/mysql-test/suite/innodb/r/innodb-autoinc.result
@@ -648,7 +648,7 @@ t2 CREATE TABLE `t2` (
`n` int(10) unsigned NOT NULL,
`o` enum('FALSE','TRUE') DEFAULT NULL,
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 ;
SHOW CREATE TABLE t1;
Table Create Table
@@ -657,7 +657,7 @@ t1 CREATE TABLE `t1` (
`b` int(10) unsigned NOT NULL,
`c` enum('FALSE','TRUE') DEFAULT NULL,
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 ;
SELECT * FROM t1;
a b c
@@ -671,16 +671,16 @@ a b c
8 4 FALSE
9 5 TRUE
10 5 FALSE
-13 1 TRUE
-14 1 FALSE
-15 2 TRUE
-16 2 FALSE
-17 3 TRUE
-18 3 FALSE
-19 4 TRUE
-20 4 FALSE
-21 5 TRUE
-22 5 FALSE
+16 1 TRUE
+17 1 FALSE
+18 2 TRUE
+19 2 FALSE
+20 3 TRUE
+21 3 FALSE
+22 4 TRUE
+23 4 FALSE
+24 5 TRUE
+25 5 FALSE
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
@@ -688,7 +688,7 @@ t1 CREATE TABLE `t1` (
`b` int(10) unsigned NOT NULL,
`c` enum('FALSE','TRUE') DEFAULT NULL,
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';
SELECT * FROM t1;
a b c
@@ -702,21 +702,21 @@ a b c
8 4 FALSE
9 5 TRUE
10 5 FALSE
-13 1 TRUE
-14 1 FALSE
-15 2 TRUE
-16 2 FALSE
-17 3 TRUE
-18 3 FALSE
-19 4 TRUE
-20 4 FALSE
-21 5 TRUE
-22 5 FALSE
-23 1 FALSE
-24 2 FALSE
-25 3 FALSE
-26 4 FALSE
-27 5 FALSE
+16 1 TRUE
+17 1 FALSE
+18 2 TRUE
+19 2 FALSE
+20 3 TRUE
+21 3 FALSE
+22 4 TRUE
+23 4 FALSE
+24 5 TRUE
+25 5 FALSE
+31 1 FALSE
+32 2 FALSE
+33 3 FALSE
+34 4 FALSE
+35 5 FALSE
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
@@ -724,7 +724,7 @@ t1 CREATE TABLE `t1` (
`b` int(10) unsigned NOT NULL,
`c` enum('FALSE','TRUE') DEFAULT NULL,
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';
SELECT * FROM t1;
a b c
@@ -738,26 +738,26 @@ a b c
8 4 FALSE
9 5 TRUE
10 5 FALSE
-13 1 TRUE
-14 1 FALSE
-15 2 TRUE
-16 2 FALSE
-17 3 TRUE
-18 3 FALSE
-19 4 TRUE
-20 4 FALSE
-21 5 TRUE
-22 5 FALSE
-23 1 FALSE
-24 2 FALSE
-25 3 FALSE
-26 4 FALSE
-27 5 FALSE
-30 1 FALSE
-31 2 FALSE
-32 3 FALSE
-33 4 FALSE
-34 5 FALSE
+16 1 TRUE
+17 1 FALSE
+18 2 TRUE
+19 2 FALSE
+20 3 TRUE
+21 3 FALSE
+22 4 TRUE
+23 4 FALSE
+24 5 TRUE
+25 5 FALSE
+31 1 FALSE
+32 2 FALSE
+33 3 FALSE
+34 4 FALSE
+35 5 FALSE
+38 1 FALSE
+39 2 FALSE
+40 3 FALSE
+41 4 FALSE
+42 5 FALSE
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
@@ -765,7 +765,7 @@ t1 CREATE TABLE `t1` (
`b` int(10) unsigned NOT NULL,
`c` enum('FALSE','TRUE') DEFAULT NULL,
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';
SHOW CREATE TABLE t1;
Table Create Table
@@ -774,7 +774,7 @@ t1 CREATE TABLE `t1` (
`b` int(10) unsigned NOT NULL,
`c` enum('FALSE','TRUE') DEFAULT NULL,
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';
SHOW CREATE TABLE t1;
Table Create Table
@@ -783,7 +783,7 @@ t1 CREATE TABLE `t1` (
`b` int(10) unsigned NOT NULL,
`c` enum('FALSE','TRUE') DEFAULT NULL,
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';
SELECT * FROM t1;
a b c
@@ -797,41 +797,41 @@ a b c
8 4 FALSE
9 5 TRUE
10 5 FALSE
-13 1 TRUE
-14 1 FALSE
-15 2 TRUE
-16 2 FALSE
-17 3 TRUE
-18 3 FALSE
-19 4 TRUE
-20 4 FALSE
-21 5 TRUE
-22 5 FALSE
-23 1 FALSE
-24 2 FALSE
-25 3 FALSE
-26 4 FALSE
-27 5 FALSE
-30 1 FALSE
-31 2 FALSE
-32 3 FALSE
-33 4 FALSE
-34 5 FALSE
-37 1 FALSE
-38 2 FALSE
-39 3 FALSE
-40 4 FALSE
-41 5 FALSE
-44 1 FALSE
-45 2 FALSE
-46 3 FALSE
-47 4 FALSE
-48 5 FALSE
-51 1 FALSE
-52 2 FALSE
-53 3 FALSE
-54 4 FALSE
-55 5 FALSE
+16 1 TRUE
+17 1 FALSE
+18 2 TRUE
+19 2 FALSE
+20 3 TRUE
+21 3 FALSE
+22 4 TRUE
+23 4 FALSE
+24 5 TRUE
+25 5 FALSE
+31 1 FALSE
+32 2 FALSE
+33 3 FALSE
+34 4 FALSE
+35 5 FALSE
+38 1 FALSE
+39 2 FALSE
+40 3 FALSE
+41 4 FALSE
+42 5 FALSE
+45 1 FALSE
+46 2 FALSE
+47 3 FALSE
+48 4 FALSE
+49 5 FALSE
+52 1 FALSE
+53 2 FALSE
+54 3 FALSE
+55 4 FALSE
+56 5 FALSE
+59 1 FALSE
+60 2 FALSE
+61 3 FALSE
+62 4 FALSE
+63 5 FALSE
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
@@ -839,7 +839,7 @@ t1 CREATE TABLE `t1` (
`b` int(10) unsigned NOT NULL,
`c` enum('FALSE','TRUE') DEFAULT NULL,
PRIMARY KEY (`a`)
-) ENGINE=InnoDB AUTO_INCREMENT=58 DEFAULT CHARSET=latin1
+) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=latin1
DROP TABLE t1;
DROP TABLE t2;
DROP TABLE IF EXISTS t1;
@@ -1251,3 +1251,21 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=18446744073709551615 DEFAULT CHARSET=latin1
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;
diff --git a/mysql-test/suite/innodb/t/innodb-autoinc.test b/mysql-test/suite/innodb/t/innodb-autoinc.test
index c3b64c7c963..5e5a40b3c89 100644
--- a/mysql-test/suite/innodb/t/innodb-autoinc.test
+++ b/mysql-test/suite/innodb/t/innodb-autoinc.test
@@ -637,3 +637,14 @@ INSERT INTO t1 VALUES (18446744073709551615);
-- source include/restart_mysqld.inc
SHOW CREATE 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;
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 9d4f99975c0..9679a901e20 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -1447,70 +1447,87 @@ values we want to reserve for multi-value inserts e.g.,
INSERT INTO T VALUES(), (), ();
-innobase_next_autoinc() will be called with increment set to
-n * 3 where autoinc_lock_mode != TRADITIONAL because we want
-to reserve 3 values for the multi-value INSERT above.
+innobase_next_autoinc() will be called with increment set to 3 where
+autoinc_lock_mode != TRADITIONAL because we want to reserve 3 values for
+the multi-value INSERT above.
@return the next value */
static
ulonglong
innobase_next_autoinc(
/*==================*/
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 max_value) /*!< in: max value for type */
{
ulonglong next_value;
+ ulonglong block = need * step;
/* 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
- the increment then the offset is ignored. */
- if (offset > increment) {
+ the step then the offset is ignored. */
+ if (offset > block) {
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;
- } else if (offset <= 1) {
- /* Offset 0 and 1 are the same, because there must be at
- least one node in the system. */
- if (max_value - current <= increment) {
+ } else {
+ ut_a(max_value > current);
+
+ ulonglong free = max_value - current;
+
+ if (free < offset || free - offset <= block) {
next_value = max_value;
} else {
- next_value = current + increment;
+ next_value = 0;
}
- } else if (max_value > current) {
+ }
+
+ if (next_value == 0) {
+ ulonglong next;
+
if (current > offset) {
- next_value = ((current - offset) / increment) + 1;
+ next = (current - offset) / step;
} else {
- next_value = ((offset - current) / increment) + 1;
+ next = (offset - current) / step;
}
- ut_a(increment > 0);
- ut_a(next_value > 0);
-
+ ut_a(max_value > next);
+ next_value = next * step;
/* 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;
- } else {
- next_value *= increment;
+ /* Check for overflow */
+ if (max_value - next_value >= block) {
- ut_a(max_value >= next_value);
+ next_value += block;
- /* Check for overflow. */
- if (max_value - next_value <= offset) {
- next_value = max_value;
- } else {
+ if (max_value - next_value >= offset) {
next_value += offset;
+ } else {
+ next_value = max_value;
}
+ } else {
+ next_value = max_value;
}
- } else {
- next_value = max_value;
}
+ ut_a(next_value != 0);
ut_a(next_value <= max_value);
return(next_value);
@@ -3746,7 +3763,7 @@ ha_innobase::innobase_initialize_autoinc()
nor the offset, so use a default increment of 1. */
auto_inc = innobase_next_autoinc(
- read_auto_inc, 1, 1, col_max_value);
+ read_auto_inc, 1, 1, 0, col_max_value);
break;
}
@@ -5246,15 +5263,16 @@ set_max_autoinc:
if (auto_inc <= col_max_value) {
ut_a(prebuilt->autoinc_increment > 0);
- ulonglong need;
ulonglong offset;
+ ulonglong increment;
offset = prebuilt->autoinc_offset;
- need = prebuilt->autoinc_increment;
+ increment = prebuilt->autoinc_increment;
auto_inc = innobase_next_autoinc(
auto_inc,
- need, offset, col_max_value);
+ 1, increment, offset,
+ col_max_value);
err = innobase_set_max_autoinc(
auto_inc);
@@ -5522,14 +5540,14 @@ ha_innobase::update_row(
if (auto_inc <= col_max_value && auto_inc != 0) {
- ulonglong need;
ulonglong offset;
+ ulonglong increment;
offset = prebuilt->autoinc_offset;
- need = prebuilt->autoinc_increment;
+ increment = prebuilt->autoinc_increment;
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);
}
@@ -10139,16 +10157,15 @@ ha_innobase::get_auto_increment(
/* With old style AUTOINC locking we only update the table's
AUTOINC counter after attempting to insert the row. */
if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
- ulonglong need;
ulonglong current;
ulonglong next_value;
current = *first_value > col_max_value ? autoinc : *first_value;
- need = *nb_reserved_values * increment;
/* Compute the last value in the interval */
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;