Commit 332ea21b authored by sunny's avatar sunny

Add a table level counter that tracks the number of AUTOINC locks that are

pending and/or granted on a table. We peek at this value to determine whether
a transaction doing a simple INSERT in innodb_autoinc_lock_mode = 1, needs to
acquire the AUTOINC lock or not. This change is related to Bug# 16979.
parent 78860498
...@@ -95,6 +95,10 @@ dict_mem_table_create( ...@@ -95,6 +95,10 @@ dict_mem_table_create(
default to 1 here.*/ default to 1 here.*/
table->autoinc_increment = 1; table->autoinc_increment = 1;
/* The number of transactions that are either waiting on the
AUTOINC lock or have been granted the lock. */
table->n_waiting_or_granted_auto_inc_locks = 0;
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
table->magic_n = DICT_TABLE_MAGIC_N; table->magic_n = DICT_TABLE_MAGIC_N;
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
......
...@@ -3270,16 +3270,16 @@ ha_innobase::innobase_autoinc_lock(void) ...@@ -3270,16 +3270,16 @@ ha_innobase::innobase_autoinc_lock(void)
the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
etc. type of statement. */ etc. type of statement. */
if (thd_sql_command(user_thd) == SQLCOM_INSERT) { if (thd_sql_command(user_thd) == SQLCOM_INSERT) {
dict_table_t* table = prebuilt->table;
/* Acquire the AUTOINC mutex. */ /* Acquire the AUTOINC mutex. */
dict_table_autoinc_lock(prebuilt->table); dict_table_autoinc_lock(table);
/* We peek at the dict_table_t::auto_inc_lock
to check if another statement has locked it. */
if (prebuilt->trx->auto_inc_lock != NULL) {
/* We need to check that another transaction isn't
already holding the AUTOINC lock on the table. */
if (table->n_waiting_or_granted_auto_inc_locks) {
/* Release the mutex to avoid deadlocks. */ /* Release the mutex to avoid deadlocks. */
dict_table_autoinc_unlock(prebuilt->table); dict_table_autoinc_unlock(table);
} else { } else {
break; break;
} }
......
...@@ -416,6 +416,16 @@ struct dict_table_struct{ ...@@ -416,6 +416,16 @@ struct dict_table_struct{
/* The increment step of the auto increment /* The increment step of the auto increment
column. Value must be greater than or equal column. Value must be greater than or equal
to 1 */ to 1 */
ulong n_waiting_or_granted_auto_inc_locks;
/* This counter is used to track the number
of granted and pending autoinc locks on this
table. This value is set after acquiring the
kernel mutex but we peek the contents to
determine whether other transactions have
acquired the AUTOINC lock or not. Of course
only one transaction can be granted the
lock but there can be multiple waiters. */
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
ulint magic_n;/* magic number */ ulint magic_n;/* magic number */
# define DICT_TABLE_MAGIC_N 76333786 # define DICT_TABLE_MAGIC_N 76333786
......
...@@ -3386,6 +3386,10 @@ lock_table_create( ...@@ -3386,6 +3386,10 @@ lock_table_create(
ut_ad(table && trx); ut_ad(table && trx);
ut_ad(mutex_own(&kernel_mutex)); ut_ad(mutex_own(&kernel_mutex));
if ((type_mode & LOCK_MODE_MASK) == LOCK_AUTO_INC) {
++table->n_waiting_or_granted_auto_inc_locks;
}
if (type_mode == LOCK_AUTO_INC) { if (type_mode == LOCK_AUTO_INC) {
/* Only one trx can have the lock on the table /* Only one trx can have the lock on the table
at a time: we may use the memory preallocated at a time: we may use the memory preallocated
...@@ -3436,6 +3440,9 @@ lock_table_remove_low( ...@@ -3436,6 +3440,9 @@ lock_table_remove_low(
if (lock == trx->auto_inc_lock) { if (lock == trx->auto_inc_lock) {
trx->auto_inc_lock = NULL; trx->auto_inc_lock = NULL;
ut_a(table->n_waiting_or_granted_auto_inc_locks > 0);
--table->n_waiting_or_granted_auto_inc_locks;
} }
UT_LIST_REMOVE(trx_locks, trx->trx_locks, lock); UT_LIST_REMOVE(trx_locks, trx->trx_locks, lock);
......
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