Merge InnoDB snapshot with mysql-5.1-bugteam.
This commit is contained in:
commit
a365016f8b
30
mysql-test/r/innodb-autoinc-44030.result
Normal file
30
mysql-test/r/innodb-autoinc-44030.result
Normal file
@ -0,0 +1,30 @@
|
||||
drop table if exists t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
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
|
||||
2
|
||||
SELECT * FROM t1;
|
||||
d1
|
||||
1
|
||||
2
|
||||
INSERT INTO t1 VALUES(null);
|
||||
Got one of the listed errors
|
||||
ALTER TABLE t1 AUTO_INCREMENT = 3;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`d1` int(11) NOT NULL AUTO_INCREMENT,
|
||||
PRIMARY KEY (`d1`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
|
||||
INSERT INTO t1 VALUES(null);
|
||||
SELECT * FROM t1;
|
||||
d1
|
||||
1
|
||||
2
|
||||
3
|
||||
DROP TABLE t1;
|
@ -868,35 +868,6 @@ Got one of the listed errors
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
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
|
||||
2
|
||||
SELECT * FROM t1;
|
||||
d1
|
||||
1
|
||||
2
|
||||
INSERT INTO t1 VALUES(null);
|
||||
Got one of the listed errors
|
||||
ALTER TABLE t1 AUTO_INCREMENT = 3;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`d1` int(11) NOT NULL AUTO_INCREMENT,
|
||||
PRIMARY KEY (`d1`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
|
||||
INSERT INTO t1 VALUES(null);
|
||||
SELECT * FROM t1;
|
||||
d1
|
||||
1
|
||||
2
|
||||
3
|
||||
DROP TABLE t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
Variable_name Value
|
||||
auto_increment_increment 1
|
||||
|
@ -11,3 +11,4 @@
|
||||
##############################################################################
|
||||
kill : Bug#37780 2008-12-03 HHunger need some changes to be robust enough for pushbuild.
|
||||
query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically
|
||||
innodb-autoinc-44030 : BUG#47621 2009-01-22 svoj MySQL and InnoDB dicts getting out of sync
|
||||
|
34
mysql-test/t/innodb-autoinc-44030.test
Normal file
34
mysql-test/t/innodb-autoinc-44030.test
Normal file
@ -0,0 +1,34 @@
|
||||
-- source include/have_innodb.inc
|
||||
# embedded server ignores 'delayed', so skip this
|
||||
-- source include/not_embedded.inc
|
||||
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
|
||||
#
|
||||
# 44030: Error: (1500) Couldn't read the MAX(ID) autoinc value from
|
||||
# the index (PRIMARY)
|
||||
# This test requires a restart of the server
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
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;
|
||||
# MySQL have made a change (http://lists.mysql.com/commits/75268) that no
|
||||
# longer results in the two data dictionaries being out of sync. If they
|
||||
# revert their changes then this check for ER_AUTOINC_READ_FAILED will need
|
||||
# to be enabled. Also, see http://bugs.mysql.com/bug.php?id=47621.
|
||||
-- error ER_AUTOINC_READ_FAILED,1467
|
||||
INSERT INTO t1 VALUES(null);
|
||||
ALTER TABLE t1 AUTO_INCREMENT = 3;
|
||||
SHOW CREATE TABLE t1;
|
||||
INSERT INTO t1 VALUES(null);
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
@ -478,32 +478,6 @@ 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
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
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;
|
||||
# MySQL have made a change (http://lists.mysql.com/commits/75268) that no
|
||||
# longer results in the two data dictionaries being out of sync. If they
|
||||
# revert their changes then this check for ER_AUTOINC_READ_FAILED will need
|
||||
# to be enabled.
|
||||
-- error ER_AUTOINC_READ_FAILED,1467
|
||||
INSERT INTO t1 VALUES(null);
|
||||
ALTER TABLE t1 AUTO_INCREMENT = 3;
|
||||
SHOW CREATE TABLE t1;
|
||||
INSERT INTO t1 VALUES(null);
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
# If the user has specified negative values for an AUTOINC column then
|
||||
# InnoDB should ignore those values when setting the table's max value.
|
||||
|
@ -15,6 +15,8 @@
|
||||
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
let $MYSQLD_DATADIR= `select @@datadir`;
|
||||
|
||||
# Save the original values of some variables in order to be able to
|
||||
# estimate how much they have changed during the tests. Previously this
|
||||
# test assumed that e.g. rows_deleted is 0 here and after deleting 23
|
||||
@ -1699,7 +1701,7 @@ set foreign_key_checks=0;
|
||||
create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1;
|
||||
create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8;
|
||||
# Embedded server doesn't chdir to data directory
|
||||
--replace_result $MYSQLTEST_VARDIR . mysqld.1/data/ ''
|
||||
--replace_result $MYSQLD_DATADIR ./ master-data/ ''
|
||||
-- error 1025
|
||||
rename table t3 to t1;
|
||||
set foreign_key_checks=1;
|
||||
@ -2339,7 +2341,7 @@ ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1 (a) ON DELETE SET NULL;
|
||||
# mysqltest first does replace_regex, then replace_result
|
||||
--replace_regex /'[^']*test\/#sql-[0-9a-f_]*'/'#sql-temporary'/
|
||||
# Embedded server doesn't chdir to data directory
|
||||
--replace_result $MYSQLTEST_VARDIR . mysqld.1/data/ ''
|
||||
--replace_result $MYSQLD_DATADIR ./ master-data/ ''
|
||||
--error 1025
|
||||
ALTER TABLE t2 MODIFY a INT NOT NULL;
|
||||
DELETE FROM t1;
|
||||
|
@ -2575,58 +2575,151 @@ normalize_table_name(
|
||||
#endif
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Get the upper limit of the MySQL integral and floating-point type. */
|
||||
static
|
||||
ulonglong
|
||||
innobase_get_int_col_max_value(
|
||||
/*===========================*/
|
||||
/* out: maximum allowed value for the field */
|
||||
const Field* field) /* in: MySQL field */
|
||||
{
|
||||
ulonglong max_value = 0;
|
||||
|
||||
switch(field->key_type()) {
|
||||
/* TINY */
|
||||
case HA_KEYTYPE_BINARY:
|
||||
max_value = 0xFFULL;
|
||||
break;
|
||||
case HA_KEYTYPE_INT8:
|
||||
max_value = 0x7FULL;
|
||||
break;
|
||||
/* SHORT */
|
||||
case HA_KEYTYPE_USHORT_INT:
|
||||
max_value = 0xFFFFULL;
|
||||
break;
|
||||
case HA_KEYTYPE_SHORT_INT:
|
||||
max_value = 0x7FFFULL;
|
||||
break;
|
||||
/* MEDIUM */
|
||||
case HA_KEYTYPE_UINT24:
|
||||
max_value = 0xFFFFFFULL;
|
||||
break;
|
||||
case HA_KEYTYPE_INT24:
|
||||
max_value = 0x7FFFFFULL;
|
||||
break;
|
||||
/* LONG */
|
||||
case HA_KEYTYPE_ULONG_INT:
|
||||
max_value = 0xFFFFFFFFULL;
|
||||
break;
|
||||
case HA_KEYTYPE_LONG_INT:
|
||||
max_value = 0x7FFFFFFFULL;
|
||||
break;
|
||||
/* BIG */
|
||||
case HA_KEYTYPE_ULONGLONG:
|
||||
max_value = 0xFFFFFFFFFFFFFFFFULL;
|
||||
break;
|
||||
case HA_KEYTYPE_LONGLONG:
|
||||
max_value = 0x7FFFFFFFFFFFFFFFULL;
|
||||
break;
|
||||
case HA_KEYTYPE_FLOAT:
|
||||
/* We use the maximum as per IEEE754-2008 standard, 2^24 */
|
||||
max_value = 0x1000000ULL;
|
||||
break;
|
||||
case HA_KEYTYPE_DOUBLE:
|
||||
/* We use the maximum as per IEEE754-2008 standard, 2^53 */
|
||||
max_value = 0x20000000000000ULL;
|
||||
break;
|
||||
default:
|
||||
ut_error;
|
||||
}
|
||||
|
||||
return(max_value);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Set the autoinc column max value. This should only be called once from
|
||||
ha_innobase::open(). Therefore there's no need for a covering lock. */
|
||||
|
||||
ulong
|
||||
void
|
||||
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;
|
||||
|
||||
col_name = table->found_next_number_field->field_name;
|
||||
index = innobase_get_index(table->s->next_number_index);
|
||||
|
||||
/* Execute SELECT MAX(col_name) FROM TABLE; */
|
||||
error = row_search_max_autoinc(index, col_name, &auto_inc);
|
||||
|
||||
if (error == DB_SUCCESS) {
|
||||
|
||||
/* At the this stage we dont' know the increment
|
||||
or the offset, so use default inrement of 1. */
|
||||
++auto_inc;
|
||||
|
||||
dict_table_autoinc_initialize(innodb_table, auto_inc);
|
||||
|
||||
} else if (error == DB_RECORD_NOT_FOUND) {
|
||||
ut_print_timestamp(stderr);
|
||||
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);
|
||||
const Field* field = table->found_next_number_field;
|
||||
|
||||
if (field != NULL) {
|
||||
auto_inc = innobase_get_int_col_max_value(field);
|
||||
} else {
|
||||
/* We have no idea what's been passed in to us as the
|
||||
autoinc column. We set it to the MAX_INT of our table
|
||||
autoinc type. */
|
||||
auto_inc = 0xFFFFFFFFFFFFFFFFULL;
|
||||
|
||||
dict_table_autoinc_initialize(innodb_table, auto_inc);
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr, " InnoDB: Unable to determine the AUTOINC "
|
||||
"column name\n");
|
||||
}
|
||||
|
||||
error = DB_SUCCESS;
|
||||
} /* else other errors are still fatal */
|
||||
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
|
||||
/* If the recovery level is set so high that writes
|
||||
are disabled we force the AUTOINC counter to the MAX
|
||||
value effectively disabling writes to the table.
|
||||
Secondly, we avoid reading the table in case the read
|
||||
results in failure due to a corrupted table/index.
|
||||
|
||||
return(ulong(error));
|
||||
We will not return an error to the client, so that the
|
||||
tables can be dumped with minimal hassle. If an error
|
||||
were returned in this case, the first attempt to read
|
||||
the table would fail and subsequent SELECTs would succeed. */
|
||||
} else if (field == NULL) {
|
||||
my_error(ER_AUTOINC_READ_FAILED, MYF(0));
|
||||
} else {
|
||||
dict_index_t* index;
|
||||
const char* col_name;
|
||||
ulonglong read_auto_inc;
|
||||
ulint err;
|
||||
|
||||
update_thd(ha_thd());
|
||||
col_name = field->field_name;
|
||||
index = innobase_get_index(table->s->next_number_index);
|
||||
|
||||
/* Execute SELECT MAX(col_name) FROM TABLE; */
|
||||
err = row_search_max_autoinc(index, col_name, &read_auto_inc);
|
||||
|
||||
switch (err) {
|
||||
case DB_SUCCESS:
|
||||
/* At the this stage we do not know the increment
|
||||
or the offset, so use a default increment of 1. */
|
||||
auto_inc = read_auto_inc + 1;
|
||||
break;
|
||||
|
||||
case DB_RECORD_NOT_FOUND:
|
||||
ut_print_timestamp(stderr);
|
||||
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);
|
||||
|
||||
my_error(ER_AUTOINC_READ_FAILED, MYF(0));
|
||||
break;
|
||||
default:
|
||||
/* row_search_max_autoinc() should only return
|
||||
one of DB_SUCCESS or DB_RECORD_NOT_FOUND. */
|
||||
ut_error;
|
||||
}
|
||||
}
|
||||
|
||||
dict_table_autoinc_initialize(prebuilt->table, auto_inc);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
@ -2824,8 +2917,6 @@ retry:
|
||||
|
||||
/* Only if the table has an AUTOINC column. */
|
||||
if (prebuilt->table != NULL && table->found_next_number_field != NULL) {
|
||||
ulint error;
|
||||
|
||||
dict_table_autoinc_lock(prebuilt->table);
|
||||
|
||||
/* Since a table can already be "open" in InnoDB's internal
|
||||
@ -2834,8 +2925,7 @@ retry:
|
||||
autoinc value from a previous MySQL open. */
|
||||
if (dict_table_autoinc_read(prebuilt->table) == 0) {
|
||||
|
||||
error = innobase_initialize_autoinc();
|
||||
ut_a(error == DB_SUCCESS);
|
||||
innobase_initialize_autoinc();
|
||||
}
|
||||
|
||||
dict_table_autoinc_unlock(prebuilt->table);
|
||||
@ -3650,67 +3740,6 @@ skip_field:
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Get the upper limit of the MySQL integral and floating-point type. */
|
||||
|
||||
ulonglong
|
||||
ha_innobase::innobase_get_int_col_max_value(
|
||||
/*========================================*/
|
||||
const Field* field)
|
||||
{
|
||||
ulonglong max_value = 0;
|
||||
|
||||
switch(field->key_type()) {
|
||||
/* TINY */
|
||||
case HA_KEYTYPE_BINARY:
|
||||
max_value = 0xFFULL;
|
||||
break;
|
||||
case HA_KEYTYPE_INT8:
|
||||
max_value = 0x7FULL;
|
||||
break;
|
||||
/* SHORT */
|
||||
case HA_KEYTYPE_USHORT_INT:
|
||||
max_value = 0xFFFFULL;
|
||||
break;
|
||||
case HA_KEYTYPE_SHORT_INT:
|
||||
max_value = 0x7FFFULL;
|
||||
break;
|
||||
/* MEDIUM */
|
||||
case HA_KEYTYPE_UINT24:
|
||||
max_value = 0xFFFFFFULL;
|
||||
break;
|
||||
case HA_KEYTYPE_INT24:
|
||||
max_value = 0x7FFFFFULL;
|
||||
break;
|
||||
/* LONG */
|
||||
case HA_KEYTYPE_ULONG_INT:
|
||||
max_value = 0xFFFFFFFFULL;
|
||||
break;
|
||||
case HA_KEYTYPE_LONG_INT:
|
||||
max_value = 0x7FFFFFFFULL;
|
||||
break;
|
||||
/* BIG */
|
||||
case HA_KEYTYPE_ULONGLONG:
|
||||
max_value = 0xFFFFFFFFFFFFFFFFULL;
|
||||
break;
|
||||
case HA_KEYTYPE_LONGLONG:
|
||||
max_value = 0x7FFFFFFFFFFFFFFFULL;
|
||||
break;
|
||||
case HA_KEYTYPE_FLOAT:
|
||||
/* We use the maximum as per IEEE754-2008 standard, 2^24 */
|
||||
max_value = 0x1000000ULL;
|
||||
break;
|
||||
case HA_KEYTYPE_DOUBLE:
|
||||
/* We use the maximum as per IEEE754-2008 standard, 2^53 */
|
||||
max_value = 0x20000000000000ULL;
|
||||
break;
|
||||
default:
|
||||
ut_error;
|
||||
}
|
||||
|
||||
return(max_value);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
This special handling is really to overcome the limitations of MySQL's
|
||||
binlogging. We need to eliminate the non-determinism that will arise in
|
||||
|
@ -78,9 +78,8 @@ class ha_innobase: public handler
|
||||
ulong innobase_reset_autoinc(ulonglong auto_inc);
|
||||
ulong innobase_get_autoinc(ulonglong* value);
|
||||
ulong innobase_update_autoinc(ulonglong auto_inc);
|
||||
ulong innobase_initialize_autoinc();
|
||||
void innobase_initialize_autoinc();
|
||||
dict_index_t* innobase_get_index(uint keynr);
|
||||
ulonglong innobase_get_int_col_max_value(const Field* field);
|
||||
|
||||
/* Init values for the class: */
|
||||
public:
|
||||
|
@ -3245,19 +3245,13 @@ check_next_foreign:
|
||||
"END;\n"
|
||||
, FALSE, trx);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
ut_a(err == DB_OUT_OF_FILE_SPACE);
|
||||
|
||||
err = DB_MUST_GET_MORE_FILE_SPACE;
|
||||
|
||||
row_mysql_handle_errors(&err, trx, NULL, NULL);
|
||||
|
||||
ut_error;
|
||||
} else {
|
||||
switch (err) {
|
||||
ibool is_path;
|
||||
const char* name_or_path;
|
||||
mem_heap_t* heap;
|
||||
|
||||
case DB_SUCCESS:
|
||||
|
||||
heap = mem_heap_create(200);
|
||||
|
||||
/* Clone the name, in case it has been allocated
|
||||
@ -3322,7 +3316,27 @@ check_next_foreign:
|
||||
}
|
||||
|
||||
mem_heap_free(heap);
|
||||
break;
|
||||
|
||||
case DB_TOO_MANY_CONCURRENT_TRXS:
|
||||
/* Cannot even find a free slot for the
|
||||
the undo log. We can directly exit here
|
||||
and return the DB_TOO_MANY_CONCURRENT_TRXS
|
||||
error. */
|
||||
break;
|
||||
|
||||
case DB_OUT_OF_FILE_SPACE:
|
||||
err = DB_MUST_GET_MORE_FILE_SPACE;
|
||||
|
||||
row_mysql_handle_errors(&err, trx, NULL, NULL);
|
||||
|
||||
/* Fall through to raise error */
|
||||
|
||||
default:
|
||||
/* No other possible error returns */
|
||||
ut_error;
|
||||
}
|
||||
|
||||
funct_exit:
|
||||
|
||||
trx_commit_for_mysql(trx);
|
||||
|
Loading…
x
Reference in New Issue
Block a user