diff options
author | Marko Mäkelä <marko.makela@oracle.com> | 2011-04-11 17:03:32 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@oracle.com> | 2011-04-11 17:03:32 +0300 |
commit | 460a7197bb0bda8401f947e30d6aec2b4acb9fb3 (patch) | |
tree | b851fa825337e1df319fa715979f0d3387378863 /storage/innobase/trx | |
parent | 3dc70ced6f3a36c3a8a161d0040f389680cc6263 (diff) | |
parent | 12fbe05c6a31a7958a4a1cae748477027fffa51f (diff) | |
download | mariadb-git-460a7197bb0bda8401f947e30d6aec2b4acb9fb3.tar.gz |
Merge mysql-5.1-innodb to mysql-5.5-innodb.
Diffstat (limited to 'storage/innobase/trx')
-rw-r--r-- | storage/innobase/trx/trx0sys.c | 10 | ||||
-rw-r--r-- | storage/innobase/trx/trx0trx.c | 68 | ||||
-rw-r--r-- | storage/innobase/trx/trx0undo.c | 28 |
3 files changed, 105 insertions, 1 deletions
diff --git a/storage/innobase/trx/trx0sys.c b/storage/innobase/trx/trx0sys.c index 7af9fbb1af8..8e595353024 100644 --- a/storage/innobase/trx/trx0sys.c +++ b/storage/innobase/trx/trx0sys.c @@ -37,6 +37,7 @@ Created 3/26/1996 Heikki Tuuri #include "trx0rseg.h" #include "trx0undo.h" #include "srv0srv.h" +#include "srv0start.h" #include "trx0purge.h" #include "log0log.h" #include "log0recv.h" @@ -1617,10 +1618,12 @@ void trx_sys_close(void) /*===============*/ { + trx_t* trx; trx_rseg_t* rseg; read_view_t* view; ut_ad(trx_sys != NULL); + ut_ad(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS); /* Check that all read views are closed except read view owned by a purge. */ @@ -1652,6 +1655,13 @@ trx_sys_close(void) mem_free(trx_doublewrite); trx_doublewrite = NULL; + /* Only prepared transactions may be left in the system. Free them. */ + ut_a(UT_LIST_GET_LEN(trx_sys->trx_list) == trx_n_prepared); + + while ((trx = UT_LIST_GET_FIRST(trx_sys->trx_list)) != NULL) { + trx_free_prepared(trx); + } + /* There can't be any active transactions. */ rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list); diff --git a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c index 475e2a51c8c..7b99b86c732 100644 --- a/storage/innobase/trx/trx0trx.c +++ b/storage/innobase/trx/trx0trx.c @@ -50,6 +50,9 @@ UNIV_INTERN sess_t* trx_dummy_sess = NULL; /** Number of transactions currently allocated for MySQL: protected by the kernel mutex */ UNIV_INTERN ulint trx_n_mysql_transactions = 0; +/** Number of transactions currently in the XA PREPARED state: protected by +the kernel mutex */ +UNIV_INTERN ulint trx_n_prepared = 0; #ifdef UNIV_PFS_MUTEX /* Key to register the mutex with performance schema */ @@ -338,6 +341,60 @@ trx_free( } /********************************************************************//** +At shutdown, frees a transaction object that is in the PREPARED state. */ +UNIV_INTERN +void +trx_free_prepared( +/*==============*/ + trx_t* trx) /*!< in, own: trx object */ +{ + ut_ad(mutex_own(&kernel_mutex)); + ut_a(trx->conc_state == TRX_PREPARED); + ut_a(trx->magic_n == TRX_MAGIC_N); + + /* Prepared transactions are sort of active; they allow + ROLLBACK and COMMIT operations. Because the system does not + contain any other transactions than prepared transactions at + the shutdown stage and because a transaction cannot become + PREPARED while holding locks, it is safe to release the locks + held by PREPARED transactions here at shutdown.*/ + lock_release_off_kernel(trx); + + trx_undo_free_prepared(trx); + + mutex_free(&trx->undo_mutex); + + if (trx->undo_no_arr) { + trx_undo_arr_free(trx->undo_no_arr); + } + + ut_a(UT_LIST_GET_LEN(trx->signals) == 0); + ut_a(UT_LIST_GET_LEN(trx->reply_signals) == 0); + + ut_a(trx->wait_lock == NULL); + ut_a(UT_LIST_GET_LEN(trx->wait_thrs) == 0); + + ut_a(!trx->has_search_latch); + + ut_a(trx->dict_operation_lock_mode == 0); + + if (trx->lock_heap) { + mem_heap_free(trx->lock_heap); + } + + if (trx->global_read_view_heap) { + mem_heap_free(trx->global_read_view_heap); + } + + ut_a(ib_vector_is_empty(trx->autoinc_locks)); + ib_vector_free(trx->autoinc_locks); + + UT_LIST_REMOVE(trx_list, trx_sys->trx_list, trx); + + mem_free(trx); +} + +/********************************************************************//** Frees a transaction object for MySQL. */ UNIV_INTERN void @@ -467,6 +524,7 @@ trx_lists_init_at_db_start(void) if (srv_force_recovery == 0) { trx->conc_state = TRX_PREPARED; + trx_n_prepared++; } else { fprintf(stderr, "InnoDB: Since" @@ -543,6 +601,7 @@ trx_lists_init_at_db_start(void) trx->conc_state = TRX_PREPARED; + trx_n_prepared++; } else { fprintf(stderr, "InnoDB: Since" @@ -877,6 +936,11 @@ trx_commit_off_kernel( ut_ad(trx->conc_state == TRX_ACTIVE || trx->conc_state == TRX_PREPARED); ut_ad(mutex_own(&kernel_mutex)); + if (UNIV_UNLIKELY(trx->conc_state == TRX_PREPARED)) { + ut_a(trx_n_prepared > 0); + trx_n_prepared--; + } + /* The following assignment makes the transaction committed in memory and makes its changes to data visible to other transactions. NOTE that there is a small discrepancy from the strict formal @@ -1901,6 +1965,7 @@ trx_prepare_off_kernel( /*--------------------------------------*/ trx->conc_state = TRX_PREPARED; + trx_n_prepared++; /*--------------------------------------*/ if (lsn) { @@ -2077,7 +2142,8 @@ trx_get_trx_by_xid( of gtrid_length+bqual_length bytes should be the same */ - if (trx->conc_state == TRX_PREPARED + if (trx->is_recovered + && trx->conc_state == TRX_PREPARED && xid->gtrid_length == trx->xid.gtrid_length && xid->bqual_length == trx->xid.bqual_length && memcmp(xid->data, trx->xid.data, diff --git a/storage/innobase/trx/trx0undo.c b/storage/innobase/trx/trx0undo.c index 4021a2ed573..070d6332a4f 100644 --- a/storage/innobase/trx/trx0undo.c +++ b/storage/innobase/trx/trx0undo.c @@ -36,6 +36,7 @@ Created 3/26/1996 Heikki Tuuri #include "trx0rseg.h" #include "trx0trx.h" #include "srv0srv.h" +#include "srv0start.h" #include "trx0rec.h" #include "trx0purge.h" @@ -1975,4 +1976,31 @@ trx_undo_insert_cleanup( mutex_exit(&(rseg->mutex)); } + +/********************************************************************//** +At shutdown, frees the undo logs of a PREPARED transaction. */ +UNIV_INTERN +void +trx_undo_free_prepared( +/*===================*/ + trx_t* trx) /*!< in/out: PREPARED transaction */ +{ + mutex_enter(&trx->rseg->mutex); + + ut_ad(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS); + + if (trx->update_undo) { + ut_a(trx->update_undo->state == TRX_UNDO_PREPARED); + UT_LIST_REMOVE(undo_list, trx->rseg->update_undo_list, + trx->update_undo); + trx_undo_mem_free(trx->update_undo); + } + if (trx->insert_undo) { + ut_a(trx->insert_undo->state == TRX_UNDO_PREPARED); + UT_LIST_REMOVE(undo_list, trx->rseg->insert_undo_list, + trx->insert_undo); + trx_undo_mem_free(trx->insert_undo); + } + mutex_exit(&trx->rseg->mutex); +} #endif /* !UNIV_HOTBACKUP */ |