Commit 2326c270 authored by Timothy Smith's avatar Timothy Smith

Apply InnoDB snapshot innodb-5.1-ss2858, part 13. Fixes

Bug #40224: New AUTOINC changes mask reporting of deadlock/timeout errors


Detailed revision comments:

r2849 | sunny | 2008-10-22 12:01:18 +0300 (Wed, 22 Oct 2008) | 8 lines
branches/5.1: Return the actual error code encountered when allocating
a new autoinc value. The change in behavior (bug) was introduced in 5.1.22
when we introduced the new AUTOINC locking model.

rb://31
parent 6e1f8c87
...@@ -3561,8 +3561,20 @@ ha_innobase::write_row( ...@@ -3561,8 +3561,20 @@ ha_innobase::write_row(
/* This is the case where the table has an auto-increment column */ /* This is the case where the table has an auto-increment column */
if (table->next_number_field && record == table->record[0]) { if (table->next_number_field && record == table->record[0]) {
/* Reset the error code before calling
innobase_get_auto_increment(). */
prebuilt->autoinc_error = DB_SUCCESS;
if ((error = update_auto_increment())) { if ((error = update_auto_increment())) {
/* We don't want to mask autoinc overflow errors. */
if (prebuilt->autoinc_error != DB_SUCCESS) {
error = prebuilt->autoinc_error;
goto report_error;
}
/* MySQL errors are passed straight back. */
goto func_exit; goto func_exit;
} }
...@@ -3658,6 +3670,7 @@ ha_innobase::write_row( ...@@ -3658,6 +3670,7 @@ ha_innobase::write_row(
innodb_srv_conc_exit_innodb(prebuilt->trx); innodb_srv_conc_exit_innodb(prebuilt->trx);
report_error:
error = convert_error_code_to_mysql(error, user_thd); error = convert_error_code_to_mysql(error, user_thd);
func_exit: func_exit:
...@@ -6056,25 +6069,12 @@ ha_innobase::info( ...@@ -6056,25 +6069,12 @@ ha_innobase::info(
if (flag & HA_STATUS_AUTO && table->found_next_number_field) { if (flag & HA_STATUS_AUTO && table->found_next_number_field) {
ulonglong auto_inc; ulonglong auto_inc;
int ret;
/* The following function call can the first time fail in
a lock wait timeout error because it reserves the auto-inc
lock on the table. If it fails, then someone is already initing
the auto-inc counter, and the second call is guaranteed to
succeed. */
ret = innobase_read_and_init_auto_inc(&auto_inc);
if (ret != 0) { if (innobase_read_and_init_auto_inc(&auto_inc) != 0) {
ret = innobase_read_and_init_auto_inc(&auto_inc); sql_print_error("Cannot get table %s auto-inc"
"counter value in ::info\n",
if (ret != 0) { ib_table->name);
sql_print_error("Cannot get table %s auto-inc" auto_inc = 0;
"counter value in ::info\n",
ib_table->name);
auto_inc = 0;
}
} }
stats.auto_increment_value = auto_inc; stats.auto_increment_value = auto_inc;
...@@ -7459,7 +7459,6 @@ ha_innobase::innobase_read_and_init_auto_inc( ...@@ -7459,7 +7459,6 @@ ha_innobase::innobase_read_and_init_auto_inc(
if (auto_inc == 0) { if (auto_inc == 0) {
dict_index_t* index; dict_index_t* index;
ulint error;
const char* autoinc_col_name; const char* autoinc_col_name;
ut_a(!innodb_table->autoinc_inited); ut_a(!innodb_table->autoinc_inited);
...@@ -7468,10 +7467,10 @@ ha_innobase::innobase_read_and_init_auto_inc( ...@@ -7468,10 +7467,10 @@ ha_innobase::innobase_read_and_init_auto_inc(
autoinc_col_name = table->found_next_number_field->field_name; autoinc_col_name = table->found_next_number_field->field_name;
error = row_search_max_autoinc( prebuilt->autoinc_error = row_search_max_autoinc(
index, autoinc_col_name, &auto_inc); index, autoinc_col_name, &auto_inc);
if (error == DB_SUCCESS) { if (prebuilt->autoinc_error == DB_SUCCESS) {
if (auto_inc < ~0x0ULL) { if (auto_inc < ~0x0ULL) {
++auto_inc; ++auto_inc;
} }
...@@ -7480,7 +7479,7 @@ ha_innobase::innobase_read_and_init_auto_inc( ...@@ -7480,7 +7479,7 @@ ha_innobase::innobase_read_and_init_auto_inc(
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Error: (%lu) Couldn't read " fprintf(stderr, " InnoDB: Error: (%lu) Couldn't read "
"the max AUTOINC value from the index (%s).\n", "the max AUTOINC value from the index (%s).\n",
error, index->name); prebuilt->autoinc_error, index->name);
mysql_error = 1; mysql_error = 1;
} }
...@@ -7511,22 +7510,23 @@ ha_innobase::innobase_read_and_init_auto_inc( ...@@ -7511,22 +7510,23 @@ ha_innobase::innobase_read_and_init_auto_inc(
Read the next autoinc value, initialize the table if it's not initialized. Read the next autoinc value, initialize the table if it's not initialized.
On return if there is no error then the tables AUTOINC lock is locked.*/ On return if there is no error then the tables AUTOINC lock is locked.*/
ulong ulint
ha_innobase::innobase_get_auto_increment( ha_innobase::innobase_get_auto_increment(
/*=====================================*/ /*=====================================*/
ulonglong* value) /* out: autoinc value */ ulonglong* value) /* out: autoinc value */
{ {
ulong error;
*value = 0; *value = 0;
/* Note: If the table is not initialized when we attempt the /* Note: If the table is not initialized when we attempt the
read below. We initialize the table's auto-inc counter and read below. We initialize the table's auto-inc counter and
always do a reread of the AUTOINC value. */ always do a reread of the AUTOINC value. */
do { do {
error = innobase_autoinc_lock(); /* We need to send the correct error code to the client
because handler::get_auto_increment() doesn't allow a way
to return the specific error for why it failed. */
prebuilt->autoinc_error = innobase_autoinc_lock();
if (error == DB_SUCCESS) { if (prebuilt->autoinc_error == DB_SUCCESS) {
ulonglong autoinc; ulonglong autoinc;
/* Determine the first value of the interval */ /* Determine the first value of the interval */
...@@ -7548,46 +7548,17 @@ ha_innobase::innobase_get_auto_increment( ...@@ -7548,46 +7548,17 @@ ha_innobase::innobase_get_auto_increment(
/* Just to make sure */ /* Just to make sure */
ut_a(!trx->auto_inc_lock); ut_a(!trx->auto_inc_lock);
int mysql_error; /* Will set prebuilt->autoinc_error if there
is a problem during init. */
mysql_error = innobase_read_and_init_auto_inc( innobase_read_and_init_auto_inc(&autoinc);
&autoinc);
if (mysql_error) {
error = DB_ERROR;
}
} else { } else {
*value = autoinc; *value = autoinc;
} }
/* We need to send the messages to the client because
handler::get_auto_increment() doesn't allow a way
to return the specific error for why it failed. */
} else if (error == DB_DEADLOCK) {
THD* thd = ha_thd();
push_warning(
thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
ER_LOCK_DEADLOCK,
"InnoDB: Deadlock in "
"innobase_get_auto_increment()");
} else if (error == DB_LOCK_WAIT_TIMEOUT) {
THD* thd = ha_thd();
push_warning(
thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
ER_LOCK_WAIT_TIMEOUT,
"InnoDB: Lock wait timeout in "
"innobase_get_auto_increment()");
} else {
sql_print_error(
"InnoDB: Error: %lu in "
"innobase_get_auto_increment()",
error);
} }
} while (*value == 0 && error == DB_SUCCESS); } while (*value == 0 && prebuilt->autoinc_error == DB_SUCCESS);
return(error); return(prebuilt->autoinc_error);
} }
/******************************************************************************* /*******************************************************************************
......
...@@ -692,6 +692,11 @@ struct row_prebuilt_struct { ...@@ -692,6 +692,11 @@ struct row_prebuilt_struct {
ulonglong autoinc_offset; /* The offset passed to ulonglong autoinc_offset; /* The offset passed to
get_auto_increment() by MySQL. Required get_auto_increment() by MySQL. Required
to calculate the next value */ to calculate the next value */
ulint autoinc_error; /* The actual error code encountered
while trying to init or read the
autoinc value from the table. We
store it here so that we can return
it to MySQL */
/*----------------------*/ /*----------------------*/
ulint magic_n2; /* this should be the same as ulint magic_n2; /* this should be the same as
magic_n */ magic_n */
......
...@@ -661,6 +661,7 @@ row_create_prebuilt( ...@@ -661,6 +661,7 @@ row_create_prebuilt(
prebuilt->old_vers_heap = NULL; prebuilt->old_vers_heap = NULL;
prebuilt->autoinc_error = 0;
prebuilt->autoinc_offset = 0; prebuilt->autoinc_offset = 0;
/* Default to 1, we will set the actual value later in /* Default to 1, we will set the actual value later in
......
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