mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
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
This commit is contained in:
@@ -3561,8 +3561,20 @@ no_commit:
|
|||||||
/* 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 @@ set_max_autoinc:
|
|||||||
|
|
||||||
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(
|
|||||||
|
|
||||||
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
|
if (innobase_read_and_init_auto_inc(&auto_inc) != 0) {
|
||||||
a lock wait timeout error because it reserves the auto-inc
|
sql_print_error("Cannot get table %s auto-inc"
|
||||||
lock on the table. If it fails, then someone is already initing
|
"counter value in ::info\n",
|
||||||
the auto-inc counter, and the second call is guaranteed to
|
ib_table->name);
|
||||||
succeed. */
|
auto_inc = 0;
|
||||||
|
|
||||||
ret = innobase_read_and_init_auto_inc(&auto_inc);
|
|
||||||
|
|
||||||
if (ret != 0) {
|
|
||||||
ret = innobase_read_and_init_auto_inc(&auto_inc);
|
|
||||||
|
|
||||||
if (ret != 0) {
|
|
||||||
sql_print_error("Cannot get table %s auto-inc"
|
|
||||||
"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(
|
|||||||
|
|
||||||
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(
|
|||||||
|
|
||||||
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(
|
|||||||
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(
|
|||||||
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(
|
|||||||
/* 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. */
|
||||||
|
innobase_read_and_init_auto_inc(&autoinc);
|
||||||
|
|
||||||
mysql_error = innobase_read_and_init_auto_inc(
|
|
||||||
&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 {
|
|||||||
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(
|
|||||||
|
|
||||||
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
|
||||||
|
Reference in New Issue
Block a user