diff options
Diffstat (limited to 'innobase/lock/lock0lock.c')
-rw-r--r-- | innobase/lock/lock0lock.c | 102 |
1 files changed, 98 insertions, 4 deletions
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index ea035dbdeb0..2f5ade656d9 100644 --- a/innobase/lock/lock0lock.c +++ b/innobase/lock/lock0lock.c @@ -301,6 +301,11 @@ struct lock_struct{ } un_member; }; +/* We store info on the latest deadlock error to this buffer. InnoDB +Monitor will then fetch it and print */ +ibool lock_deadlock_found = FALSE; +char* lock_latest_err_buf; /* We allocate 5000 bytes for this */ + /************************************************************************ Checks if a lock request results in a deadlock. */ static @@ -575,6 +580,8 @@ lock_sys_create( lock_sys->rec_hash = hash_create(n_cells); /* hash_create_mutexes(lock_sys->rec_hash, 2, SYNC_REC_LOCK); */ + + lock_latest_err_buf = mem_alloc(5000); } /************************************************************************* @@ -2698,6 +2705,7 @@ lock_deadlock_occurs( trx_t* mark_trx; ibool ret; ulint cost = 0; + char* err_buf; ut_ad(trx && lock); ut_ad(mutex_own(&kernel_mutex)); @@ -2723,6 +2731,29 @@ lock_deadlock_occurs( index = lock->index; table = index->table; } + + lock_deadlock_found = TRUE; + + err_buf = lock_latest_err_buf + strlen(lock_latest_err_buf); + + err_buf += sprintf(err_buf, + "*** (2) WAITING FOR THIS LOCK TO BE GRANTED:\n"); + + ut_a(err_buf <= lock_latest_err_buf + 4000); + + if (lock_get_type(lock) == LOCK_REC) { + lock_rec_print(err_buf, lock); + err_buf += strlen(err_buf); + } else { + lock_table_print(err_buf, lock); + err_buf += strlen(err_buf); + } + + ut_a(err_buf <= lock_latest_err_buf + 4000); + + err_buf += sprintf(err_buf, + "*** WE ROLL BACK TRANSACTION (2)\n"); + /* sess_raise_error_low(trx, DB_DEADLOCK, lock->type_mode, table, index, NULL, NULL, NULL); @@ -2750,6 +2781,7 @@ lock_deadlock_recursive( lock_t* lock; ulint bit_no; trx_t* lock_trx; + char* err_buf; ut_a(trx && start && wait_lock); ut_ad(mutex_own(&kernel_mutex)); @@ -2801,6 +2833,53 @@ lock_deadlock_recursive( lock_trx = lock->trx; if (lock_trx == start) { + err_buf = lock_latest_err_buf; + + ut_sprintf_timestamp(err_buf); + err_buf += strlen(err_buf); + + err_buf += sprintf(err_buf, + " LATEST DETECTED DEADLOCK:\n" + "*** (1) TRANSACTION:\n"); + + trx_print(err_buf, wait_lock->trx); + err_buf += strlen(err_buf); + + err_buf += sprintf(err_buf, + "*** (1) WAITING FOR THIS LOCK TO BE GRANTED:\n"); + + ut_a(err_buf <= lock_latest_err_buf + 4000); + + if (lock_get_type(wait_lock) == LOCK_REC) { + lock_rec_print(err_buf, wait_lock); + err_buf += strlen(err_buf); + } else { + lock_table_print(err_buf, wait_lock); + err_buf += strlen(err_buf); + } + + ut_a(err_buf <= lock_latest_err_buf + 4000); + err_buf += sprintf(err_buf, + "*** (2) TRANSACTION:\n"); + + trx_print(err_buf, lock->trx); + err_buf += strlen(err_buf); + + err_buf += sprintf(err_buf, + "*** (2) HOLDS THE LOCK(S):\n"); + + ut_a(err_buf <= lock_latest_err_buf + 4000); + + if (lock_get_type(lock) == LOCK_REC) { + lock_rec_print(err_buf, lock); + err_buf += strlen(err_buf); + } else { + lock_table_print(err_buf, lock); + err_buf += strlen(err_buf); + } + + ut_a(err_buf <= lock_latest_err_buf + 4000); + if (lock_print_waits) { printf("Deadlock detected\n"); } @@ -3433,6 +3512,9 @@ lock_rec_print( buf += sprintf(buf, "Suppressing further record lock prints for this page\n"); + + mtr_commit(&mtr); + return; } @@ -3505,10 +3587,6 @@ lock_print_info( return; } - buf += sprintf(buf, "Number of sessions %lu\n", - UT_LIST_GET_LEN(trx_sys->mysql_trx_list) - + UT_LIST_GET_LEN(trx_sys->trx_list)); - buf += sprintf(buf, "Trx id counter %lu %lu\n", ut_dulint_get_high(trx_sys->max_trx_id), ut_dulint_get_low(trx_sys->max_trx_id)); @@ -3525,6 +3603,22 @@ lock_print_info( buf += sprintf(buf, "Total number of lock structs in row lock hash table %lu\n", lock_get_n_rec_locks()); + if (lock_deadlock_found) { + + if ((ulint)(buf_end - buf) + < 100 + strlen(lock_latest_err_buf)) { + + return; + } + + buf += sprintf(buf, "%s", lock_latest_err_buf); + } + + if (buf_end - buf < 600) { + return; + } + + buf += sprintf(buf, "LIST OF TRANSACTIONS FOR EACH SESSION:\n"); /* First print info on non-active transactions */ |