summaryrefslogtreecommitdiff
path: root/innobase
diff options
context:
space:
mode:
authorunknown <heikki@hundin.mysql.fi>2002-11-07 14:47:25 +0200
committerunknown <heikki@hundin.mysql.fi>2002-11-07 14:47:25 +0200
commit4fa5e50edbba856a2fe60d1dde7eb5571f42bd68 (patch)
tree55c72cdc1d8c91f0b56057c2e2c01f7ce3c93883 /innobase
parent8fc4319ae36e106ed8474a567bd1bd00e6337d5f (diff)
downloadmariadb-git-4fa5e50edbba856a2fe60d1dde7eb5571f42bd68.tar.gz
Many files:
Fix hang introduced by selective deadlock resolution srv0srv.c, row0mysql.c: Fix hang introduced by selective deadlock resolution + corruption caused by lock timeout or sel deadl res in ON DELETE CASCADE innobase/include/que0que.h: Fix hang introduced by selective deadlock resolution innobase/include/trx0trx.h: Fix hang introduced by selective deadlock resolution innobase/include/ut0ut.h: Fix hang introduced by selective deadlock resolution innobase/lock/lock0lock.c: Fix hang introduced by selective deadlock resolution innobase/log/log0log.c: Fix hang introduced by selective deadlock resolution innobase/que/que0que.c: Fix hang introduced by selective deadlock resolution innobase/row/row0mysql.c: Fix hang introduced by selective deadlock resolution + corruption caused by lock timeout or sel deadl res in ON DELETE CASCADE innobase/srv/srv0srv.c: Fix hang introduced by selective deadlock resolution + corruption caused by lock timeout or sel deadl res in ON DELETE CASCADE innobase/trx/trx0sys.c: Fix hang introduced by selective deadlock resolution innobase/trx/trx0trx.c: Fix hang introduced by selective deadlock resolution
Diffstat (limited to 'innobase')
-rw-r--r--innobase/include/que0que.h8
-rw-r--r--innobase/include/trx0trx.h11
-rw-r--r--innobase/include/ut0ut.h1
-rw-r--r--innobase/lock/lock0lock.c5
-rw-r--r--innobase/log/log0log.c4
-rw-r--r--innobase/que/que0que.c24
-rw-r--r--innobase/row/row0mysql.c30
-rw-r--r--innobase/srv/srv0srv.c19
-rw-r--r--innobase/trx/trx0sys.c2
-rw-r--r--innobase/trx/trx0trx.c1
10 files changed, 81 insertions, 24 deletions
diff --git a/innobase/include/que0que.h b/innobase/include/que0que.h
index cdaeeae1fde..a3ed18e2b14 100644
--- a/innobase/include/que0que.h
+++ b/innobase/include/que0que.h
@@ -117,6 +117,7 @@ que_thr_stop(
/**************************************************************************
Moves a thread from another state to the QUE_THR_RUNNING state. Increments
the n_active_thrs counters of the query graph and transaction. */
+
void
que_thr_move_to_run_state_for_mysql(
/*================================*/
@@ -125,14 +126,17 @@ que_thr_move_to_run_state_for_mysql(
/**************************************************************************
A patch for MySQL used to 'stop' a dummy query thread used in MySQL
select, when there is no error or lock wait. */
+
void
que_thr_stop_for_mysql_no_error(
/*============================*/
que_thr_t* thr, /* in: query thread */
trx_t* trx); /* in: transaction */
/**************************************************************************
-A patch for MySQL used to 'stop' a dummy query thread used in MySQL
-select. */
+A patch for MySQL used to 'stop' a dummy query thread used in MySQL. The
+query thread is stopped and made inactive, except in the case where
+it was put to the lock wait state in lock0lock.c, but the lock has already
+been granted or the transaction chosen as a victim in deadlock resolution. */
void
que_thr_stop_for_mysql(
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index 1468ef449e7..34f820f03e7 100644
--- a/innobase/include/trx0trx.h
+++ b/innobase/include/trx0trx.h
@@ -429,7 +429,10 @@ struct trx_struct{
MySQL */
/*------------------------------*/
ulint error_state; /* 0 if no error, otherwise error
- number */
+ number; NOTE That ONLY the thread
+ doing the transaction is allowed to
+ set this field: this is NOT protected
+ by the kernel mutex */
void* error_info; /* if the error number indicates a
duplicate key error, a pointer to
the problematic index is stored here */
@@ -466,6 +469,12 @@ struct trx_struct{
TRX_QUE_LOCK_WAIT, this points to
the lock request, otherwise this is
NULL */
+ ibool was_chosen_as_deadlock_victim;
+ /* when the transaction decides to wait
+ for a lock, this it sets this to FALSE;
+ if another transaction chooses this
+ transaction as a victim in deadlock
+ resolution, it sets this to TRUE */
time_t wait_started; /* lock wait started at this time */
UT_LIST_BASE_NODE_T(que_thr_t)
wait_thrs; /* query threads belonging to this
diff --git a/innobase/include/ut0ut.h b/innobase/include/ut0ut.h
index d4697c47266..8ec23b23dcd 100644
--- a/innobase/include/ut0ut.h
+++ b/innobase/include/ut0ut.h
@@ -10,7 +10,6 @@ Created 1/20/1994 Heikki Tuuri
#define ut0ut_h
#include "univ.i"
-#include <string.h>
#include <time.h>
#ifndef MYSQL_SERVER
#include <ctype.h>
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index 92ee5ee6cbe..7b08d6b89b8 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -1727,6 +1727,7 @@ index->table_name);
}
trx->que_state = TRX_QUE_LOCK_WAIT;
+ trx->was_chosen_as_deadlock_victim = FALSE;
trx->wait_started = time(NULL);
ut_a(que_thr_stop(thr));
@@ -3173,7 +3174,8 @@ lock_deadlock_recursive(
err_buf += sprintf(err_buf,
"*** WE ROLL BACK TRANSACTION (1)\n");
- wait_lock->trx->error_state = DB_DEADLOCK;
+ wait_lock->trx->was_chosen_as_deadlock_victim
+ = TRUE;
lock_cancel_waiting_and_release(wait_lock);
@@ -3353,6 +3355,7 @@ table->name);
}
trx->que_state = TRX_QUE_LOCK_WAIT;
+ trx->was_chosen_as_deadlock_victim = FALSE;
trx->wait_started = time(NULL);
ut_a(que_thr_stop(thr));
diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c
index f9b785ccbd5..c798a08e2de 100644
--- a/innobase/log/log0log.c
+++ b/innobase/log/log0log.c
@@ -1654,8 +1654,8 @@ log_reset_first_header_and_checkpoint(
lsn = ut_dulint_add(start, LOG_BLOCK_HDR_SIZE);
/* Write the label of ibbackup --restore */
- sprintf((char*) hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, "ibbackup ");
- ut_sprintf_timestamp((char*) hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP
+ sprintf(hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, "ibbackup ");
+ ut_sprintf_timestamp(hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP
+ strlen("ibbackup "));
buf = hdr_buf + LOG_CHECKPOINT_1;
diff --git a/innobase/que/que0que.c b/innobase/que/que0que.c
index 7fa444f6741..a96c8840a03 100644
--- a/innobase/que/que0que.c
+++ b/innobase/que/que0que.c
@@ -1046,14 +1046,16 @@ que_thr_stop(
}
/**************************************************************************
-A patch for MySQL used to 'stop' a dummy query thread used in MySQL. */
+A patch for MySQL used to 'stop' a dummy query thread used in MySQL. The
+query thread is stopped and made inactive, except in the case where
+it was put to the lock wait state in lock0lock.c, but the lock has already
+been granted or the transaction chosen as a victim in deadlock resolution. */
void
que_thr_stop_for_mysql(
/*===================*/
que_thr_t* thr) /* in: query thread */
{
- ibool stopped = FALSE;
trx_t* trx;
trx = thr_get_trx(thr);
@@ -1067,13 +1069,10 @@ que_thr_stop_for_mysql(
/* Error handling built for the MySQL interface */
thr->state = QUE_THR_COMPLETED;
-
- stopped = TRUE;
- }
-
- if (!stopped) {
- /* It must have been a lock wait but the
- lock was already released */
+ } else {
+ /* It must have been a lock wait but the lock was
+ already released, or this transaction was chosen
+ as a victim in selective deadlock resolution */
mutex_exit(&kernel_mutex);
@@ -1081,6 +1080,10 @@ que_thr_stop_for_mysql(
}
}
+ ut_ad(thr->is_active == TRUE);
+ ut_ad(trx->n_active_thrs == 1);
+ ut_ad(thr->graph->n_active_thrs == 1);
+
thr->is_active = FALSE;
(thr->graph)->n_active_thrs--;
@@ -1132,6 +1135,9 @@ que_thr_stop_for_mysql_no_error(
trx_t* trx) /* in: transaction */
{
ut_ad(thr->state == QUE_THR_RUNNING);
+ ut_ad(thr->is_active == TRUE);
+ ut_ad(trx->n_active_thrs == 1);
+ ut_ad(thr->graph->n_active_thrs == 1);
if (thr->magic_n != QUE_THR_MAGIC_N) {
fprintf(stderr,
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index b109b785a45..f228a75ad3a 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -198,8 +198,9 @@ row_mysql_handle_errors(
/* out: TRUE if it was a lock wait and
we should continue running the query thread */
ulint* new_err,/* out: possible new error encountered in
- rollback, or the old error which was
- during the function entry */
+ lock wait, or if no new error, the value
+ of trx->error_state at the entry of this
+ function */
trx_t* trx, /* in: transaction */
que_thr_t* thr, /* in: query thread */
trx_savept_t* savept) /* in: savepoint or NULL */
@@ -998,8 +999,8 @@ row_update_cascade_for_mysql(
or set null operation */
dict_table_t* table) /* in: table where we do the operation */
{
- ulint err;
- trx_t* trx;
+ ulint err;
+ trx_t* trx;
trx = thr_get_trx(thr);
run_again:
@@ -1010,11 +1011,28 @@ run_again:
err = trx->error_state;
+ /* Note that the cascade node is a subnode of another InnoDB
+ query graph node. We do a normal lock wait in this node, but
+ all errors are handled by the parent node. */
+
if (err == DB_LOCK_WAIT) {
- que_thr_stop_for_mysql(thr);
+ /* Handle lock wait here */
- row_mysql_handle_errors(&err, trx, thr, NULL);
+ que_thr_stop_for_mysql(thr);
+ srv_suspend_mysql_thread(thr);
+
+ /* Note that a lock wait may also end in a lock wait timeout,
+ or this transaction is picked as a victim in selective
+ deadlock resolution */
+
+ if (trx->error_state != DB_SUCCESS) {
+
+ return(trx->error_state);
+ }
+
+ /* Retry operation after a normal lock wait */
+
goto run_again;
}
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index 51d7878fd29..f9eba721cbc 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -2082,13 +2082,24 @@ srv_suspend_mysql_thread(
if (thr->state == QUE_THR_RUNNING) {
- /* The lock has already been released: no need to suspend */
+ ut_ad(thr->is_active == TRUE);
+
+ /* The lock has already been released or this transaction
+ was chosen as a deadlock victim: no need to suspend */
+
+ if (trx->was_chosen_as_deadlock_victim) {
+
+ trx->error_state = DB_DEADLOCK;
+ trx->was_chosen_as_deadlock_victim = FALSE;
+ }
mutex_exit(&kernel_mutex);
return;
}
+ ut_ad(thr->is_active == FALSE);
+
slot = srv_table_reserve_slot_for_mysql();
event = slot->event;
@@ -2142,6 +2153,12 @@ srv_suspend_mysql_thread(
wait_time = ut_difftime(ut_time(), slot->suspend_time);
+ if (trx->was_chosen_as_deadlock_victim) {
+
+ trx->error_state = DB_DEADLOCK;
+ trx->was_chosen_as_deadlock_victim = FALSE;
+ }
+
mutex_exit(&kernel_mutex);
if (srv_lock_wait_timeout < 100000000 &&
diff --git a/innobase/trx/trx0sys.c b/innobase/trx/trx0sys.c
index 19cf52c8676..33c962772e8 100644
--- a/innobase/trx/trx0sys.c
+++ b/innobase/trx/trx0sys.c
@@ -474,7 +474,7 @@ trx_sys_update_mysql_binlog_offset(
mlog_write_string(sys_header + field
+ TRX_SYS_MYSQL_LOG_NAME,
- (byte*) file_name, 1 + ut_strlen(file_name), mtr);
+ file_name, 1 + ut_strlen(file_name), mtr);
}
if (mach_read_from_4(sys_header + field
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index 9f711890f60..f0077f941de 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -129,6 +129,7 @@ trx_create(
trx->graph = NULL;
trx->wait_lock = NULL;
+ trx->was_chosen_as_deadlock_victim = FALSE;
UT_LIST_INIT(trx->wait_thrs);
trx->lock_heap = mem_heap_create_in_buffer(256);