diff --git a/handler/ha_innodb.cc b/handler/ha_innodb.cc index 0471282e1d5..b6beb6876d2 100644 --- a/handler/ha_innodb.cc +++ b/handler/ha_innodb.cc @@ -2971,8 +2971,7 @@ ha_innobase::innobase_initialize_autoinc() dict_index_t* index; ulonglong auto_inc; const char* col_name; - ulint error = DB_SUCCESS; - dict_table_t* innodb_table = prebuilt->table; + ulint error; col_name = table->found_next_number_field->field_name; index = innobase_get_index(table->s->next_number_index); @@ -2980,22 +2979,40 @@ ha_innobase::innobase_initialize_autoinc() /* Execute SELECT MAX(col_name) FROM TABLE; */ error = row_search_max_autoinc(index, col_name, &auto_inc); - if (error == DB_SUCCESS) { + switch (error) { + case DB_SUCCESS: - /* At the this stage we dont' know the increment + /* At the this stage we don't know the increment or the offset, so use default inrement of 1. */ ++auto_inc; + break; - dict_table_autoinc_initialize(innodb_table, auto_inc); - - } else { + case DB_RECORD_NOT_FOUND: ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: Error: (%lu) Couldn't read " - "the MAX(%s) autoinc value from the " - "index (%s).\n", error, col_name, index->name); + fprintf(stderr, " InnoDB: MySQL and InnoDB data " + "dictionaries are out of sync.\n" + "InnoDB: Unable to find the AUTOINC column %s in the " + "InnoDB table %s.\n" + "InnoDB: We set the next AUTOINC column value to the " + "maximum possible value,\n" + "InnoDB: in effect disabling the AUTOINC next value " + "generation.\n" + "InnoDB: You can either set the next AUTOINC value " + "explicitly using ALTER TABLE\n" + "InnoDB: or fix the data dictionary by recreating " + "the table.\n", + col_name, index->table->name); + + auto_inc = 0xFFFFFFFFFFFFFFFFULL; + break; + + default: + return(error); } - return(error); + dict_table_autoinc_initialize(prebuilt->table, auto_inc); + + return(DB_SUCCESS); } /*****************************************************************//** @@ -3213,7 +3230,6 @@ retry: if (dict_table_autoinc_read(prebuilt->table) == 0) { error = innobase_initialize_autoinc(); - /* Should always succeed! */ ut_a(error == DB_SUCCESS); } diff --git a/mysql-test/innodb-autoinc.result b/mysql-test/innodb-autoinc.result index ade4db35ce6..d2e8eb19e0c 100644 --- a/mysql-test/innodb-autoinc.result +++ b/mysql-test/innodb-autoinc.result @@ -867,3 +867,25 @@ INSERT INTO t2 SELECT NULL FROM t1; Got one of the listed errors DROP TABLE t1; DROP TABLE t2; +CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (null); +INSERT INTO t1 VALUES (null); +ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT; +SELECT * FROM t1; +d1 +1 +3 +SELECT * FROM t1; +d1 +1 +3 +INSERT INTO t1 VALUES(null); +Got one of the listed errors +ALTER TABLE t1 AUTO_INCREMENT = 3; +INSERT INTO t1 VALUES(null); +SELECT * FROM t1; +d1 +1 +3 +4 +DROP TABLE t1; diff --git a/mysql-test/innodb-autoinc.test b/mysql-test/innodb-autoinc.test index d76b29a7dc8..61c42f45733 100644 --- a/mysql-test/innodb-autoinc.test +++ b/mysql-test/innodb-autoinc.test @@ -478,3 +478,23 @@ INSERT INTO t2 SELECT c1 FROM t1; INSERT INTO t2 SELECT NULL FROM t1; DROP TABLE t1; DROP TABLE t2; +# +# 44030: Error: (1500) Couldn't read the MAX(ID) autoinc value from +# the index (PRIMARY) +# This test requires a restart of the server +CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (null); +INSERT INTO t1 VALUES (null); +ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT; +SELECT * FROM t1; +# Restart the server +-- source include/restart_mysqld.inc +# The MySQL and InnoDB data dictionaries should now be out of sync. +# The select should print message to the error log +SELECT * FROM t1; +-- error ER_AUTOINC_READ_FAILED,1467 +INSERT INTO t1 VALUES(null); +ALTER TABLE t1 AUTO_INCREMENT = 3; +INSERT INTO t1 VALUES(null); +SELECT * FROM t1; +DROP TABLE t1; diff --git a/mysql-test/innodb_bug45357.result b/mysql-test/innodb_bug45357.result new file mode 100644 index 00000000000..7adeff2062f --- /dev/null +++ b/mysql-test/innodb_bug45357.result @@ -0,0 +1,7 @@ +set session transaction isolation level read committed; +create table bug45357(a int, b int,key(b))engine=innodb; +insert into bug45357 values (25170,6122); +update bug45357 set a=1 where b=30131; +delete from bug45357 where b < 20996; +delete from bug45357 where b < 7001; +drop table bug45357; diff --git a/mysql-test/innodb_bug45357.test b/mysql-test/innodb_bug45357.test new file mode 100644 index 00000000000..81727f352dd --- /dev/null +++ b/mysql-test/innodb_bug45357.test @@ -0,0 +1,10 @@ +-- source include/have_innodb.inc + +set session transaction isolation level read committed; + +create table bug45357(a int, b int,key(b))engine=innodb; +insert into bug45357 values (25170,6122); +update bug45357 set a=1 where b=30131; +delete from bug45357 where b < 20996; +delete from bug45357 where b < 7001; +drop table bug45357; diff --git a/row/row0mysql.c b/row/row0mysql.c index b915de20c33..b345bb59624 100644 --- a/row/row0mysql.c +++ b/row/row0mysql.c @@ -1498,9 +1498,14 @@ row_unlock_for_mysql( index = btr_pcur_get_btr_cur(clust_pcur)->index; } + if (UNIV_UNLIKELY(!dict_index_is_clust(index))) { + /* This is not a clustered index record. We + do not know how to unlock the record. */ + goto no_unlock; + } + /* If the record has been modified by this transaction, do not unlock it. */ - ut_a(dict_index_is_clust(index)); if (index->trx_id_offset) { rec_trx_id = trx_read_trx_id(rec @@ -1540,7 +1545,7 @@ row_unlock_for_mysql( prebuilt->select_lock_type); } } - +no_unlock: mtr_commit(&mtr); }