diff options
author | Sunny Bains <Sunny.Bains@Oracle.Com> | 2012-03-29 18:02:08 +1100 |
---|---|---|
committer | Sunny Bains <Sunny.Bains@Oracle.Com> | 2012-03-29 18:02:08 +1100 |
commit | d1809a5c85bf76136aa7645c152e9f723fd4250b (patch) | |
tree | 195d41ba841264f685b0e26372213116fba55062 | |
parent | 7553f9eefdcdf67d31caa2a64b826dd476b4c35e (diff) | |
download | mariadb-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.result | 194 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/innodb-autoinc.test | 11 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 97 |
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; |