summaryrefslogtreecommitdiff
path: root/innobase/trx
diff options
context:
space:
mode:
authorunknown <monty@mysql.com>2004-06-18 04:38:58 +0300
committerunknown <monty@mysql.com>2004-06-18 04:38:58 +0300
commit2b9a8afa50c3575f924587588ce13852933d4d15 (patch)
tree7b3b07f5c8491e5a81ca71b19d92dc87ec314192 /innobase/trx
parent7d52eabb39d1733f4f10cac0f8f4d0555346ed9a (diff)
parent5fa063ba7eda4bbe70e758b2e5662dbd4edfe961 (diff)
downloadmariadb-git-2b9a8afa50c3575f924587588ce13852933d4d15.tar.gz
Merge with 4.0.21
BitKeeper/etc/logging_ok: auto-union Build-tools/mysql-copyright-2: Auto merged include/violite.h: Auto merged innobase/btr/btr0btr.c: Auto merged innobase/buf/buf0buf.c: Auto merged innobase/buf/buf0flu.c: Auto merged innobase/buf/buf0lru.c: Auto merged innobase/dict/dict0dict.c: Auto merged innobase/dict/dict0mem.c: Auto merged innobase/fsp/fsp0fsp.c: Auto merged innobase/fut/fut0lst.c: Auto merged innobase/ha/hash0hash.c: Auto merged innobase/include/buf0buf.ic: Auto merged innobase/include/buf0lru.h: Auto merged innobase/include/data0data.h: Auto merged innobase/include/dict0dict.h: Auto merged innobase/include/dict0mem.h: Auto merged innobase/include/fsp0fsp.h: Auto merged innobase/include/hash0hash.h: Auto merged innobase/include/lock0lock.h: Auto merged innobase/include/log0log.h: Auto merged innobase/include/log0log.ic: Auto merged innobase/include/mem0dbg.ic: Auto merged innobase/include/mem0pool.h: Auto merged innobase/include/mtr0mtr.h: Auto merged innobase/include/sync0rw.h: Auto merged innobase/include/sync0sync.h: Auto merged innobase/include/trx0roll.h: Auto merged innobase/include/trx0trx.h: Auto merged innobase/include/ut0mem.h: Auto merged innobase/lock/lock0lock.c: Auto merged innobase/log/log0log.c: Auto merged innobase/mem/mem0dbg.c: Auto merged innobase/mem/mem0pool.c: Auto merged innobase/mtr/mtr0mtr.c: Auto merged innobase/pars/lexyy.c: Auto merged innobase/pars/pars0opt.c: Auto merged innobase/que/que0que.c: Auto merged innobase/rem/rem0cmp.c: Auto merged innobase/row/row0ins.c: Auto merged innobase/row/row0mysql.c: Auto merged innobase/row/row0upd.c: Auto merged innobase/srv/srv0srv.c: Auto merged innobase/srv/srv0start.c: Auto merged innobase/sync/sync0rw.c: Auto merged innobase/sync/sync0sync.c: Auto merged innobase/thr/thr0loc.c: Auto merged innobase/trx/trx0purge.c: Auto merged innobase/trx/trx0roll.c: Auto merged innobase/trx/trx0sys.c: Auto merged innobase/trx/trx0trx.c: Auto merged innobase/usr/usr0sess.c: Auto merged innobase/ut/ut0mem.c: Auto merged mysql-test/r/func_if.result: Auto merged mysql-test/r/type_date.result: Auto merged mysql-test/t/type_date.test: Auto merged mysql-test/t/type_decimal.test: Auto merged mysys/mf_tempfile.c: Auto merged netware/BUILD/nwbootstrap: Auto merged netware/Makefile.am: Auto merged scripts/mysqld_safe.sh: Auto merged sql/item_cmpfunc.cc: Auto merged mysql-test/t/func_if.test: Auto merged sql/mysqld.cc: Auto merged sql/opt_range.cc: Auto merged sql/sql_acl.cc: Auto merged sql/sql_parse.cc: Auto merged support-files/my-innodb-heavy-4G.cnf.sh: Auto merged Build-tools/Do-compile: Merge with 4.0 Build-tools/mysql-copyright: Merge with 4.0 client/mysqltest.c: Merge with 4.0 include/my_global.h: Merge with 4.0 innobase/buf/buf0rea.c: Merge with 4.0 innobase/data/data0type.c: Merge with 4.0 innobase/ibuf/ibuf0ibuf.c: Merge with 4.0 innobase/include/buf0buf.h: Merge with 4.0 innobase/include/data0type.h: Merge with 4.0 innobase/include/mem0mem.h: Merge with 4.0 innobase/include/mem0mem.ic: Merge with 4.0 innobase/log/log0recv.c: Merge with 4.0 libmysql/libmysql.c: Merge with 4.0 libmysqld/Makefile.am: Merge with 4.0 mysql-test/r/range.result: Merge with 4.0 mysql-test/r/type_decimal.result: Merge with 4.0 mysql-test/t/range.test: Merge with 4.0 netware/BUILD/mwenv: Merge with 4.0 netware/mysql_test_run.c: Merge with 4.0 scripts/mysql_install_db.sh: Merge with 4.0 sql/field.cc: Merge with 4.0 sql/field.h: Merge with 4.0 sql/item_cmpfunc.h: Merge with 4.0 support-files/my-huge.cnf.sh: Merge with 4.0 support-files/my-large.cnf.sh: Merge with 4.0 support-files/my-medium.cnf.sh: Merge with 4.0 support-files/my-small.cnf.sh: Merge with 4.0 support-files/mysql.spec.sh: Merge with 4.0
Diffstat (limited to 'innobase/trx')
-rw-r--r--innobase/trx/trx0purge.c3
-rw-r--r--innobase/trx/trx0roll.c79
-rw-r--r--innobase/trx/trx0sys.c2
-rw-r--r--innobase/trx/trx0trx.c165
4 files changed, 185 insertions, 64 deletions
diff --git a/innobase/trx/trx0purge.c b/innobase/trx/trx0purge.c
index 002775eaac1..3d5f0d3f03a 100644
--- a/innobase/trx/trx0purge.c
+++ b/innobase/trx/trx0purge.c
@@ -23,6 +23,7 @@ Created 3/26/1996 Heikki Tuuri
#include "row0purge.h"
#include "row0upd.h"
#include "trx0rec.h"
+#include "srv0que.h"
#include "os0thread.h"
/* The global data structure coordinating a purge */
@@ -1059,6 +1060,8 @@ trx_purge(void)
mutex_exit(&kernel_mutex);
+/* srv_que_task_enqueue(thr2); */
+
if (srv_print_thread_releases) {
fputs("Starting purge\n", stderr);
diff --git a/innobase/trx/trx0roll.c b/innobase/trx/trx0roll.c
index 8b8a079bb7f..e65755a0f73 100644
--- a/innobase/trx/trx0roll.c
+++ b/innobase/trx/trx0roll.c
@@ -20,6 +20,7 @@ Created 3/26/1996 Heikki Tuuri
#include "trx0rec.h"
#include "que0que.h"
#include "usr0sess.h"
+#include "srv0que.h"
#include "srv0start.h"
#include "row0undo.h"
#include "row0mysql.h"
@@ -931,15 +932,21 @@ trx_undo_rec_release(
/*************************************************************************
Starts a rollback operation. */
-que_thr_t*
+void
trx_rollback(
/*=========*/
- /* out: next query thread to run */
trx_t* trx, /* in: transaction */
- trx_sig_t* sig) /* in: signal starting the rollback */
+ trx_sig_t* sig, /* in: signal starting the rollback */
+ que_thr_t** next_thr)/* in/out: next query thread to run;
+ if the value which is passed in is
+ a pointer to a NULL pointer, then the
+ calling function can start running
+ a new query thread; if the passed value is
+ NULL, the parameter is ignored */
{
que_t* roll_graph;
que_thr_t* thr;
+/* que_thr_t* thr2; */
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
@@ -981,7 +988,18 @@ trx_rollback(
thr = que_fork_start_command(roll_graph);
ut_ad(thr);
- return(thr);
+
+/* thr2 = que_fork_start_command(roll_graph);
+
+ ut_ad(thr2); */
+
+ if (next_thr && (*next_thr == NULL)) {
+ *next_thr = thr;
+/* srv_que_task_enqueue_low(thr2); */
+ } else {
+ srv_que_task_enqueue_low(thr);
+/* srv_que_task_enqueue_low(thr2); */
+ }
}
/********************************************************************
@@ -1053,14 +1071,17 @@ trx_finish_error_processing(
/*************************************************************************
Finishes a partial rollback operation. */
static
-que_thr_t*
+void
trx_finish_partial_rollback_off_kernel(
/*===================================*/
- /* out: next query thread to run */
- trx_t* trx) /* in: transaction */
+ trx_t* trx, /* in: transaction */
+ que_thr_t** next_thr)/* in/out: next query thread to run;
+ if the value which is passed in is a pointer
+ to a NULL pointer, then the calling function
+ can start running a new query thread; if this
+ parameter is NULL, it is ignored */
{
trx_sig_t* sig;
- que_thr_t* next_thr;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
@@ -1071,26 +1092,29 @@ trx_finish_partial_rollback_off_kernel(
/* Remove the signal from the signal queue and send reply message
to it */
- next_thr = trx_sig_reply(sig);
+ trx_sig_reply(sig, next_thr);
trx_sig_remove(trx, sig);
trx->que_state = TRX_QUE_RUNNING;
- return(next_thr);
}
/********************************************************************
Finishes a transaction rollback. */
-que_thr_t*
+void
trx_finish_rollback_off_kernel(
/*===========================*/
- /* out: next query thread to run */
que_t* graph, /* in: undo graph which can now be freed */
- trx_t* trx) /* in: transaction */
+ trx_t* trx, /* in: transaction */
+ que_thr_t** next_thr)/* in/out: next query thread to run;
+ if the value which is passed in is
+ a pointer to a NULL pointer, then the
+ calling function can start running
+ a new query thread; if this parameter is
+ NULL, it is ignored */
{
trx_sig_t* sig;
trx_sig_t* next_sig;
- que_thr_t* next_thr;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
@@ -1105,21 +1129,21 @@ trx_finish_rollback_off_kernel(
if (sig->type == TRX_SIG_ROLLBACK_TO_SAVEPT) {
- return(trx_finish_partial_rollback_off_kernel(trx));
+ trx_finish_partial_rollback_off_kernel(trx, next_thr);
+
+ return;
} else if (sig->type == TRX_SIG_ERROR_OCCURRED) {
trx_finish_error_processing(trx);
- return(NULL);
+ return;
}
-#ifdef UNIV_DEBUG
if (lock_print_waits) {
fprintf(stderr, "Trx %lu rollback finished\n",
(ulong) ut_dulint_get_low(trx->id));
}
-#endif /* UNIV_DEBUG */
trx_commit_off_kernel(trx);
@@ -1127,23 +1151,19 @@ trx_finish_rollback_off_kernel(
send reply messages to them */
trx->que_state = TRX_QUE_RUNNING;
-
- next_thr = NULL;
+
while (sig != NULL) {
next_sig = UT_LIST_GET_NEXT(signals, sig);
if (sig->type == TRX_SIG_TOTAL_ROLLBACK) {
- ut_a(next_thr == NULL);
- next_thr = trx_sig_reply(sig);
+ trx_sig_reply(sig, next_thr);
trx_sig_remove(trx, sig);
}
sig = next_sig;
}
-
- return(next_thr);
}
/*************************************************************************
@@ -1176,6 +1196,7 @@ trx_rollback_step(
que_thr_t* thr) /* in: query thread */
{
roll_node_t* node;
+ ibool success;
ulint sig_no;
trx_savept_t* savept;
@@ -1202,13 +1223,19 @@ trx_rollback_step(
/* Send a rollback signal to the transaction */
- trx_sig_send(thr_get_trx(thr), sig_no, TRX_SIG_SELF,
- thr, savept);
+ success = trx_sig_send(thr_get_trx(thr),
+ sig_no, TRX_SIG_SELF,
+ thr, savept, NULL);
thr->state = QUE_THR_SIG_REPLY_WAIT;
mutex_exit(&kernel_mutex);
+ if (!success) {
+ /* Error in delivering the rollback signal */
+ que_thr_handle_error(thr, DB_ERROR, NULL, 0);
+ }
+
return(NULL);
}
diff --git a/innobase/trx/trx0sys.c b/innobase/trx/trx0sys.c
index b377bdb9809..5c8ae0952ef 100644
--- a/innobase/trx/trx0sys.c
+++ b/innobase/trx/trx0sys.c
@@ -619,7 +619,6 @@ trx_sys_update_mysql_binlog_offset(
MLOG_4BYTES, mtr);
}
-#ifdef UNIV_HOTBACKUP
/*********************************************************************
Prints to stderr the MySQL binlog info in the system header if the
magic number shows it valid. */
@@ -647,7 +646,6 @@ trx_sys_print_mysql_binlog_offset_from_page(
sys_header + TRX_SYS_MYSQL_LOG_INFO + TRX_SYS_MYSQL_LOG_NAME);
}
}
-#endif /* UNIV_HOTBACKUP */
/*********************************************************************
Prints to stderr the MySQL binlog offset info in the trx system header if
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index afef08dc100..a9aae48dae6 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -897,15 +897,18 @@ trx_assign_read_view(
/********************************************************************
Commits a transaction. NOTE that the kernel mutex is temporarily released. */
static
-que_thr_t*
+void
trx_handle_commit_sig_off_kernel(
/*=============================*/
- /* out: next query thread to run */
- trx_t* trx) /* in: transaction */
+ trx_t* trx, /* in: transaction */
+ que_thr_t** next_thr) /* in/out: next query thread to run;
+ if the value which is passed in is
+ a pointer to a NULL pointer, then the
+ calling function can start running
+ a new query thread */
{
trx_sig_t* sig;
trx_sig_t* next_sig;
- que_thr_t* next_thr = NULL;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
@@ -927,8 +930,7 @@ trx_handle_commit_sig_off_kernel(
if (sig->type == TRX_SIG_COMMIT) {
- ut_a(next_thr == NULL);
- next_thr = trx_sig_reply(sig);
+ trx_sig_reply(sig, next_thr);
trx_sig_remove(trx, sig);
}
@@ -936,8 +938,6 @@ trx_handle_commit_sig_off_kernel(
}
trx->que_state = TRX_QUE_RUNNING;
-
- return(next_thr);
}
/***************************************************************
@@ -999,6 +999,39 @@ trx_lock_wait_to_suspended(
trx->que_state = TRX_QUE_RUNNING;
}
+/***************************************************************
+Moves the query threads in the sig reply wait list of trx to the SUSPENDED
+state. */
+static
+void
+trx_sig_reply_wait_to_suspended(
+/*============================*/
+ trx_t* trx) /* in: transaction */
+{
+ trx_sig_t* sig;
+ que_thr_t* thr;
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
+
+ sig = UT_LIST_GET_FIRST(trx->reply_signals);
+
+ while (sig != NULL) {
+ thr = sig->receiver;
+
+ ut_ad(thr->state == QUE_THR_SIG_REPLY_WAIT);
+
+ thr->state = QUE_THR_SUSPENDED;
+
+ sig->receiver = NULL;
+
+ UT_LIST_REMOVE(reply_signals, trx->reply_signals, sig);
+
+ sig = UT_LIST_GET_FIRST(trx->reply_signals);
+ }
+}
+
/*********************************************************************
Checks the compatibility of a new signal with the other signals in the
queue. */
@@ -1078,10 +1111,11 @@ trx_sig_is_compatible(
/********************************************************************
Sends a signal to a trx object. */
-que_thr_t*
+ibool
trx_sig_send(
/*=========*/
- /* out: next query thread to run */
+ /* out: TRUE if the signal was
+ successfully delivered */
trx_t* trx, /* in: trx handle */
ulint type, /* in: signal type */
ulint sender, /* in: TRX_SIG_SELF or
@@ -1089,8 +1123,14 @@ trx_sig_send(
que_thr_t* receiver_thr, /* in: query thread which wants the
reply, or NULL; if type is
TRX_SIG_END_WAIT, this must be NULL */
- trx_savept_t* savept) /* in: possible rollback savepoint, or
+ trx_savept_t* savept, /* in: possible rollback savepoint, or
NULL */
+ que_thr_t** next_thr) /* in/out: next query thread to run;
+ if the value which is passed in is
+ a pointer to a NULL pointer, then the
+ calling function can start running
+ a new query thread; if the parameter
+ is NULL, it is ignored */
{
trx_sig_t* sig;
trx_t* receiver_trx;
@@ -1100,7 +1140,14 @@ trx_sig_send(
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
- ut_a(trx_sig_is_compatible(trx, type, sender));
+ if (!trx_sig_is_compatible(trx, type, sender)) {
+ /* The signal is not compatible with the other signals in
+ the queue: do nothing */
+
+ ut_error;
+
+ return(FALSE);
+ }
/* Queue the signal object */
@@ -1134,6 +1181,11 @@ trx_sig_send(
sig);
}
+ if (trx->sess->state == SESS_ERROR) {
+
+ trx_sig_reply_wait_to_suspended(trx);
+ }
+
if ((sender != TRX_SIG_SELF) || (type == TRX_SIG_BREAK_EXECUTION)) {
/* The following call will add a TRX_SIG_ERROR_OCCURRED
@@ -1148,10 +1200,10 @@ trx_sig_send(
if (UT_LIST_GET_FIRST(trx->signals) == sig) {
- return(trx_sig_start_handle(trx));
+ trx_sig_start_handle(trx, next_thr);
}
- return(NULL);
+ return(TRUE);
}
/********************************************************************
@@ -1173,18 +1225,27 @@ trx_end_signal_handling(
trx->handling_signals = FALSE;
trx->graph = trx->graph_before_signal_handling;
+
+ if (trx->graph && (trx->sess->state == SESS_ERROR)) {
+
+ que_fork_error_handle(trx, trx->graph);
+ }
}
/********************************************************************
Starts handling of a trx signal. */
-que_thr_t*
+void
trx_sig_start_handle(
/*=================*/
- /* out: next query thread to run, or NULL */
- trx_t* trx) /* in: trx handle */
+ trx_t* trx, /* in: trx handle */
+ que_thr_t** next_thr) /* in/out: next query thread to run;
+ if the value which is passed in is
+ a pointer to a NULL pointer, then the
+ calling function can start running
+ a new query thread; if the parameter
+ is NULL, it is ignored */
{
- que_thr_t* next_thr = NULL;
trx_sig_t* sig;
ulint type;
loop:
@@ -1200,7 +1261,7 @@ loop:
trx_end_signal_handling(trx);
- return(next_thr);
+ return;
}
if (trx->conc_state == TRX_NOT_STARTED) {
@@ -1216,13 +1277,23 @@ loop:
trx_lock_wait_to_suspended(trx);
}
+ /* If the session is in the error state and this trx has threads
+ waiting for reply from signals, moves these threads to the suspended
+ state, canceling wait reservations; note that if the transaction has
+ sent a commit or rollback signal to itself, and its session is not in
+ the error state, then nothing is done here. */
+
+ if (trx->sess->state == SESS_ERROR) {
+ trx_sig_reply_wait_to_suspended(trx);
+ }
+
/* If there are no running query threads, we can start processing of a
signal, otherwise we have to wait until all query threads of this
transaction are aware of the arrival of the signal. */
if (trx->n_active_thrs > 0) {
- return(NULL);
+ return;
}
if (trx->handling_signals == FALSE) {
@@ -1236,19 +1307,30 @@ loop:
if (type == TRX_SIG_COMMIT) {
- next_thr = trx_handle_commit_sig_off_kernel(trx);
+ trx_handle_commit_sig_off_kernel(trx, next_thr);
} else if ((type == TRX_SIG_TOTAL_ROLLBACK)
- || (type == TRX_SIG_ROLLBACK_TO_SAVEPT)
- || (type == TRX_SIG_ERROR_OCCURRED)) {
+ || (type == TRX_SIG_ROLLBACK_TO_SAVEPT)) {
+
+ trx_rollback(trx, sig, next_thr);
+
+ /* No further signals can be handled until the rollback
+ completes, therefore we return */
+
+ return;
+
+ } else if (type == TRX_SIG_ERROR_OCCURRED) {
+
+ trx_rollback(trx, sig, next_thr);
+
/* No further signals can be handled until the rollback
completes, therefore we return */
- return(trx_rollback(trx, sig));
+ return;
} else if (type == TRX_SIG_BREAK_EXECUTION) {
- next_thr = trx_sig_reply(sig);
+ trx_sig_reply(sig, next_thr);
trx_sig_remove(trx, sig);
} else {
ut_error;
@@ -1261,14 +1343,17 @@ loop:
Send the reply message when a signal in the queue of the trx has been
handled. */
-que_thr_t*
+void
trx_sig_reply(
/*==========*/
- /* out: next query thread to run */
- trx_sig_t* sig) /* in: signal */
+ trx_sig_t* sig, /* in: signal */
+ que_thr_t** next_thr) /* in/out: next query thread to run;
+ if the value which is passed in is
+ a pointer to a NULL pointer, then the
+ calling function can start running
+ a new query thread */
{
- trx_t* receiver_trx;
- que_thr_t* next_thr = NULL;
+ trx_t* receiver_trx;
ut_ad(sig);
#ifdef UNIV_SYNC_DEBUG
@@ -1282,13 +1367,13 @@ trx_sig_reply(
UT_LIST_REMOVE(reply_signals, receiver_trx->reply_signals,
sig);
- next_thr = que_thr_end_wait(sig->receiver);
+ ut_ad(receiver_trx->sess->state != SESS_ERROR);
+
+ que_thr_end_wait(sig->receiver, next_thr);
sig->receiver = NULL;
}
-
- return(next_thr);
}
/********************************************************************
@@ -1344,6 +1429,7 @@ trx_commit_step(
{
commit_node_t* node;
que_thr_t* next_thr;
+ ibool success;
node = thr->run_node;
@@ -1358,15 +1444,22 @@ trx_commit_step(
node->state = COMMIT_NODE_WAIT;
+ next_thr = NULL;
+
thr->state = QUE_THR_SIG_REPLY_WAIT;
/* Send the commit signal to the transaction */
- next_thr = trx_sig_send(thr_get_trx(thr), TRX_SIG_COMMIT,
- TRX_SIG_SELF, thr, NULL);
-
+ success = trx_sig_send(thr_get_trx(thr), TRX_SIG_COMMIT,
+ TRX_SIG_SELF, thr, NULL, &next_thr);
+
mutex_exit(&kernel_mutex);
+ if (!success) {
+ /* Error in delivering the commit signal */
+ que_thr_handle_error(thr, DB_ERROR, NULL, 0);
+ }
+
return(next_thr);
}