Browse Source

Replace trx_sys_t* trx_sys with trx_sys_t trx_sys

There is only one transaction system object in InnoDB.
Allocate the storage for it at link time, not at runtime.

lock_rec_fetch_page(): Use the correct fetch mode BUF_GET.
Pages may never be deallocated from a tablespace while
record locks are pointing to them.
pull/567/head
Marko Mäkelä 8 years ago
committed by Sergey Vojtovich
parent
commit
f8882cce93
  1. 12
      storage/innobase/btr/btr0cur.cc
  2. 6
      storage/innobase/buf/buf0buf.cc
  3. 36
      storage/innobase/handler/ha_innodb.cc
  4. 2
      storage/innobase/include/lock0lock.h
  5. 2
      storage/innobase/include/sync0types.h
  6. 78
      storage/innobase/include/trx0sys.h
  7. 30
      storage/innobase/include/trx0trx.h
  8. 4
      storage/innobase/include/trx0trx.ic
  9. 66
      storage/innobase/lock/lock0lock.cc
  10. 2
      storage/innobase/log/log0log.cc
  11. 2
      storage/innobase/page/page0page.cc
  12. 61
      storage/innobase/read/read0read.cc
  13. 2
      storage/innobase/row/row0purge.cc
  14. 6
      storage/innobase/row/row0row.cc
  15. 4
      storage/innobase/row/row0sel.cc
  16. 8
      storage/innobase/row/row0vers.cc
  17. 4
      storage/innobase/srv/srv0mon.cc
  18. 26
      storage/innobase/srv/srv0srv.cc
  19. 8
      storage/innobase/srv/srv0start.cc
  20. 13
      storage/innobase/trx/trx0i_s.cc
  21. 14
      storage/innobase/trx/trx0purge.cc
  22. 4
      storage/innobase/trx/trx0rec.cc
  23. 17
      storage/innobase/trx/trx0roll.cc
  24. 16
      storage/innobase/trx/trx0rseg.cc
  25. 89
      storage/innobase/trx/trx0sys.cc
  26. 160
      storage/innobase/trx/trx0trx.cc

12
storage/innobase/btr/btr0cur.cc

@ -482,10 +482,10 @@ inconsistent:
/* In fact, because we only ever append fields to the 'default
value' record, it is also OK to perform READ UNCOMMITTED and
then ignore any extra fields, provided that
trx_sys->rw_trx_hash.find(DB_TRX_ID). */
trx_sys.rw_trx_hash.find(DB_TRX_ID). */
if (rec_offs_n_fields(offsets) > index->n_fields
&& !trx_sys->rw_trx_hash.find(row_get_rec_trx_id(rec, index,
offsets))) {
&& !trx_sys.rw_trx_hash.find(row_get_rec_trx_id(rec, index,
offsets))) {
goto inconsistent;
}
@ -1168,7 +1168,7 @@ btr_cur_search_to_nth_level_func(
Free blocks and read IO bandwidth should be prior
for them, when the history list is glowing huge. */
if (lock_intention == BTR_INTENTION_DELETE
&& trx_sys->rseg_history_len > BTR_CUR_FINE_HISTORY_LENGTH
&& trx_sys.rseg_history_len > BTR_CUR_FINE_HISTORY_LENGTH
&& buf_get_n_pending_read_ios()) {
mtr_x_lock(dict_index_get_lock(index), mtr);
} else if (dict_index_is_spatial(index)
@ -2308,7 +2308,7 @@ btr_cur_open_at_index_side_func(
Free blocks and read IO bandwidth should be prior
for them, when the history list is glowing huge. */
if (lock_intention == BTR_INTENTION_DELETE
&& trx_sys->rseg_history_len > BTR_CUR_FINE_HISTORY_LENGTH
&& trx_sys.rseg_history_len > BTR_CUR_FINE_HISTORY_LENGTH
&& buf_get_n_pending_read_ios()) {
mtr_x_lock(dict_index_get_lock(index), mtr);
} else {
@ -2654,7 +2654,7 @@ btr_cur_open_at_rnd_pos_func(
Free blocks and read IO bandwidth should be prior
for them, when the history list is glowing huge. */
if (lock_intention == BTR_INTENTION_DELETE
&& trx_sys->rseg_history_len > BTR_CUR_FINE_HISTORY_LENGTH
&& trx_sys.rseg_history_len > BTR_CUR_FINE_HISTORY_LENGTH
&& buf_get_n_pending_read_ios()) {
mtr_x_lock(dict_index_get_lock(index), mtr);
} else {

6
storage/innobase/buf/buf0buf.cc

@ -2706,9 +2706,9 @@ withdraw_retry:
}
lock_mutex_enter();
trx_sys_mutex_enter();
mutex_enter(&trx_sys.mutex);
bool found = false;
for (trx_t* trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list);
for (trx_t* trx = UT_LIST_GET_FIRST(trx_sys.mysql_trx_list);
trx != NULL;
trx = UT_LIST_GET_NEXT(mysql_trx_list, trx)) {
if (trx->state != TRX_STATE_NOT_STARTED
@ -2730,7 +2730,7 @@ withdraw_retry:
stderr, trx);
}
}
trx_sys_mutex_exit();
mutex_exit(&trx_sys.mutex);
lock_mutex_exit();
withdraw_started = ut_time();

36
storage/innobase/handler/ha_innodb.cc

@ -319,7 +319,7 @@ thd_destructor_proxy(void *)
srv_running = NULL;
while (srv_fast_shutdown == 0 &&
(trx_sys_any_active_transactions() ||
(trx_sys.any_active_transactions() ||
(uint)thread_count > srv_n_purge_threads + 1)) {
thd_proc_info(thd, "InnoDB slow shutdown wait");
os_thread_sleep(1000);
@ -3160,9 +3160,9 @@ read view to it if there is no read view yet.
Why a deadlock of threads is not possible: the query cache calls this function
at the start of a SELECT processing. Then the calling thread cannot be
holding any InnoDB semaphores. The calling thread is holding the
query cache mutex, and this function will reserve the InnoDB trx_sys->mutex.
query cache mutex, and this function will reserve the InnoDB trx_sys.mutex.
Thus, the 'rank' in sync0mutex.h of the MySQL query cache mutex is above
the InnoDB trx_sys->mutex.
the InnoDB trx_sys.mutex.
@return TRUE if permitted, FALSE if not; note that the value FALSE
does not mean we should invalidate the query cache: invalidation is
called explicitly */
@ -3644,9 +3644,9 @@ static ulonglong innodb_prepare_commit_versioned(THD* thd, ulonglong *trx_id)
DBUG_ASSERT(t->first->versioned());
DBUG_ASSERT(trx->rsegs.m_redo.rseg);
mutex_enter(&trx_sys->mutex);
trx_id_t commit_id = trx_sys->get_new_trx_id();
mutex_exit(&trx_sys->mutex);
mutex_enter(&trx_sys.mutex);
trx_id_t commit_id = trx_sys.get_new_trx_id();
mutex_exit(&trx_sys.mutex);
return commit_id;
}
@ -16225,12 +16225,9 @@ ha_innobase::external_lock(
} else if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
&& MVCC::is_view_active(trx->read_view)) {
mutex_enter(&trx_sys->mutex);
trx_sys->mvcc->view_close(trx->read_view, true);
mutex_exit(&trx_sys->mutex);
mutex_enter(&trx_sys.mutex);
trx_sys.mvcc->view_close(trx->read_view, true);
mutex_exit(&trx_sys.mutex);
}
}
@ -16896,12 +16893,9 @@ ha_innobase::store_lock(
/* At low transaction isolation levels we let
each consistent read set its own snapshot */
mutex_enter(&trx_sys->mutex);
trx_sys->mvcc->view_close(trx->read_view, true);
mutex_exit(&trx_sys->mutex);
mutex_enter(&trx_sys.mutex);
trx_sys.mvcc->view_close(trx->read_view, true);
mutex_enter(&trx_sys.mutex);
}
}
@ -19906,9 +19900,9 @@ wsrep_fake_trx_id(
handlerton *hton,
THD *thd) /*!< in: user thread handle */
{
mutex_enter(&trx_sys->mutex);
trx_id_t trx_id = trx_sys->get_new_trx_id();
mutex_exit(&trx_sys->mutex);
mutex_enter(&trx_sys.mutex);
trx_id_t trx_id = trx_sys.get_new_trx_id();
mutex_exit(&trx_sys.mutex);
WSREP_DEBUG("innodb fake trx id: " TRX_ID_FMT " thd: %s",
trx_id, wsrep_thd_query(thd));
wsrep_ws_handle_for_trx(wsrep_thd_ws_handle(thd), trx_id);

2
storage/innobase/include/lock0lock.h

@ -609,7 +609,7 @@ lock_report_trx_id_insanity(
const rec_t* rec, /*!< in: user record */
dict_index_t* index, /*!< in: index */
const ulint* offsets, /*!< in: rec_get_offsets(rec, index) */
trx_id_t max_trx_id); /*!< in: trx_sys->get_max_trx_id() */
trx_id_t max_trx_id); /*!< in: trx_sys.get_max_trx_id() */
/*********************************************************************//**
Prints info of locks for all transactions.
@return FALSE if not able to obtain lock mutex and exits without

2
storage/innobase/include/sync0types.h

@ -160,7 +160,7 @@ V
lock_sys_mutex Mutex protecting lock_sys_t
|
V
trx_sys->mutex Mutex protecting trx_sys_t
trx_sys.mutex Mutex protecting trx_sys_t
|
V
Threads mutex Background thread scheduling mutex

78
storage/innobase/include/trx0sys.h

@ -51,9 +51,6 @@ typedef UT_LIST_BASE_NODE_T(trx_t) trx_ut_list_t;
class MVCC;
class ReadView;
/** The transaction system */
extern trx_sys_t* trx_sys;
/** Checks if a page address is the trx sys header page.
@param[in] page_id page id
@return true if trx sys header page */
@ -65,11 +62,6 @@ trx_sys_hdr_page(
/** Initialize the transaction system main-memory data structures. */
void trx_sys_init_at_db_start();
/*****************************************************************//**
Creates the trx_sys instance and initializes purge_queue and mutex. */
void
trx_sys_create(void);
/*================*/
/*****************************************************************//**
Creates and initializes the transaction system at the database creation. */
void
@ -210,23 +202,11 @@ bool
trx_sys_read_wsrep_checkpoint(XID* xid);
#endif /* WITH_WSREP */
/*****************************************************************//**
Shutdown/Close the transaction system. */
void
trx_sys_close(void);
/*===============*/
/** Create the rollback segments.
@return whether the creation succeeded */
bool
trx_sys_create_rsegs();
/*********************************************************************
Check if there are any active (non-prepared) transactions.
@return total number of active transactions or 0 if none */
ulint
trx_sys_any_active_transactions(void);
/*=================================*/
/** The automatically created system rollback segment has this id */
#define TRX_SYS_SYSTEM_RSEG_ID 0
@ -843,12 +823,11 @@ private:
number. Accessed and updated with atomic operations.
*/
char pad0[CACHE_LINE_SIZE];
trx_id_t m_max_trx_id;
char pad1[CACHE_LINE_SIZE];
MY_ALIGNED(CACHE_LINE_SIZE) trx_id_t m_max_trx_id;
public:
MY_ALIGNED(CACHE_LINE_SIZE)
TrxSysMutex mutex; /*!< mutex protecting most fields in
this structure except when noted
otherwise */
@ -863,8 +842,7 @@ public:
transactions which exist or existed */
#endif /* UNIV_DEBUG */
/** Avoid false sharing */
char pad2[CACHE_LINE_SIZE];
MY_ALIGNED(CACHE_LINE_SIZE)
trx_ut_list_t mysql_trx_list; /*!< List of transactions created
for MySQL. All user transactions are
on mysql_trx_list. The rw_trx_hash
@ -875,6 +853,7 @@ public:
transactions that have not yet been
started in InnoDB. */
MY_ALIGNED(CACHE_LINE_SIZE)
trx_ids_t rw_trx_ids; /*!< Array of Read write transaction IDs
for MVCC snapshot. A ReadView would take
a snapshot of these transactions whose
@ -884,13 +863,11 @@ public:
to ensure right order of removal and
consistent snapshot. */
/** Avoid false sharing */
char pad3[CACHE_LINE_SIZE];
MY_ALIGNED(CACHE_LINE_SIZE)
/** Temporary rollback segments */
trx_rseg_t* temp_rsegs[TRX_SYS_N_RSEGS];
/** Avoid false sharing */
char pad4[CACHE_LINE_SIZE];
MY_ALIGNED(CACHE_LINE_SIZE)
trx_rseg_t* rseg_array[TRX_SYS_N_RSEGS];
/*!< Pointer array to rollback
segments; NULL if slot not in use;
@ -904,16 +881,13 @@ public:
transactions), protected by
rseg->mutex */
char rw_trx_hash_pre_pad[CACHE_LINE_SIZE];
/**
Lock-free hash of in memory read-write transactions.
Works faster when it is on it's own cache line (tested).
*/
rw_trx_hash_t rw_trx_hash;
char rw_trx_hash_post_pad[CACHE_LINE_SIZE];
MY_ALIGNED(CACHE_LINE_SIZE) rw_trx_hash_t rw_trx_hash;
ulint n_prepared_trx; /*!< Number of transactions currently
in the XA PREPARED state */
@ -927,6 +901,17 @@ public:
transactions. We disable query cache
if such transactions exist. */
/**
Constructor.
We only initialise rw_trx_ids here as it is impossible to postpone it's
initialisation to create().
*/
trx_sys_t(): rw_trx_ids(ut_allocator<trx_id_t>(mem_key_trx_sys_t_rw_trx_ids))
{}
/**
Returns the minimum trx id in rw trx list.
@ -950,7 +935,7 @@ public:
Determines the maximum transaction id.
@return maximum currently allocated trx id; will be stale after the
next call to trx_sys->get_new_trx_id()
next call to trx_sys.get_new_trx_id()
*/
trx_id_t get_max_trx_id(void)
@ -976,7 +961,7 @@ public:
trx_id_t get_new_trx_id()
{
ut_ad(mutex_own(&trx_sys->mutex));
ut_ad(mutex_own(&mutex));
trx_id_t id= static_cast<trx_id_t>(my_atomic_add64_explicit(
reinterpret_cast<int64*>(&m_max_trx_id), 1, MY_MEMORY_ORDER_RELAXED));
@ -992,6 +977,16 @@ public:
}
/** Create the instance */
void create();
/** Close the transaction system on shutdown */
void close();
/** @return total number of active (non-prepared) transactions */
ulint any_active_transactions();
private:
static my_bool get_min_trx_id_callback(rw_trx_hash_element_t *element,
trx_id_t *id)
@ -1015,18 +1010,9 @@ private:
void flush_max_trx_id();
};
/** Test if trx_sys->mutex is owned. */
#define trx_sys_mutex_own() (trx_sys->mutex.is_owned())
/** Acquire the trx_sys->mutex. */
#define trx_sys_mutex_enter() do { \
mutex_enter(&trx_sys->mutex); \
} while (0)
/** Release the trx_sys->mutex. */
#define trx_sys_mutex_exit() do { \
trx_sys->mutex.exit(); \
} while (0)
/** The transaction system */
extern trx_sys_t trx_sys;
#include "trx0sys.ic"

30
storage/innobase/include/trx0trx.h

@ -338,7 +338,7 @@ trx_commit_step(
/**********************************************************************//**
Prints info about a transaction.
Caller must hold trx_sys->mutex. */
Caller must hold trx_sys.mutex. */
void
trx_print_low(
/*==========*/
@ -358,7 +358,7 @@ trx_print_low(
/**********************************************************************//**
Prints info about a transaction.
The caller must hold lock_sys->mutex and trx_sys->mutex.
The caller must hold lock_sys->mutex and trx_sys.mutex.
When possible, use trx_print() instead. */
void
trx_print_latched(
@ -370,7 +370,7 @@ trx_print_latched(
/**********************************************************************//**
Prints info about a transaction.
Acquires and releases lock_sys->mutex and trx_sys->mutex. */
Acquires and releases lock_sys->mutex. */
void
trx_print(
/*======*/
@ -400,9 +400,9 @@ trx_set_dict_operation(
/**********************************************************************//**
Determines if a transaction is in the given state.
The caller must hold trx_sys->mutex, or it must be the thread
The caller must hold trx_sys.mutex, or it must be the thread
that is serving a running transaction.
A running RW transaction must be in trx_sys->rw_trx_hash.
A running RW transaction must be in trx_sys.rw_trx_hash.
@return TRUE if trx->state == state */
UNIV_INLINE
bool
@ -421,7 +421,7 @@ trx_state_eq(
# ifdef UNIV_DEBUG
/**********************************************************************//**
Asserts that a transaction has been started.
The caller must hold trx_sys->mutex.
The caller must hold trx_sys.mutex.
@return TRUE if started */
ibool
trx_assert_started(
@ -822,15 +822,15 @@ so without holding any mutex. The following are exceptions to this:
* trx_rollback_resurrected() may access resurrected (connectionless)
transactions while the system is already processing new user
transactions. The trx_sys->mutex prevents a race condition between it
transactions. The trx_sys.mutex prevents a race condition between it
and lock_trx_release_locks() [invoked by trx_commit()].
* trx_print_low() may access transactions not associated with the current
thread. The caller must be holding lock_sys->mutex.
* When a transaction handle is in the trx_sys->mysql_trx_list or
trx_sys->trx_list, some of its fields must not be modified without
holding trx_sys->mutex exclusively.
* When a transaction handle is in the trx_sys.mysql_trx_list or
trx_sys.trx_list, some of its fields must not be modified without
holding trx_sys.mutex exclusively.
* The locking code (in particular, lock_deadlock_recursive() and
lock_rec_convert_impl_to_expl()) will access transactions associated
@ -978,7 +978,7 @@ public:
XA (2PC) transactions are always treated as non-autocommit.
Transitions to ACTIVE or NOT_STARTED occur when transaction
is not in rw_trx_hash (no trx_sys->mutex needed).
is not in rw_trx_hash (no trx_sys.mutex needed).
Autocommit non-locking read-only transactions move between states
without holding any mutex. They are not in rw_trx_hash.
@ -994,7 +994,7 @@ public:
it is a user transaction. It cannot be in rw_trx_hash.
ACTIVE->PREPARED->COMMITTED is only possible when trx is in rw_trx_hash.
The transition ACTIVE->PREPARED is protected by trx_sys->mutex.
The transition ACTIVE->PREPARED is protected by trx_sys.mutex.
ACTIVE->COMMITTED is possible when the transaction is in
rw_trx_hash.
@ -1022,7 +1022,7 @@ public:
or both */
bool is_recovered; /*!< 0=normal transaction,
1=recovered, must be rolled back,
protected by trx_sys->mutex when
protected by trx_sys.mutex when
trx is in rw_trx_hash */
hit_list_t hit_list; /*!< List of transactions to kill,
@ -1134,14 +1134,14 @@ public:
/*------------------------------*/
UT_LIST_NODE_T(trx_t)
mysql_trx_list; /*!< list of transactions created for
MySQL; protected by trx_sys->mutex */
MySQL; protected by trx_sys.mutex */
#ifdef UNIV_DEBUG
/** whether this transaction is updating persistent statistics
(used for silencing a debug assertion at shutdown) */
bool persistent_stats;
bool in_mysql_trx_list;
/*!< true if in
trx_sys->mysql_trx_list */
trx_sys.mysql_trx_list */
#endif /* UNIV_DEBUG */
/*------------------------------*/
dberr_t error_state; /*!< 0 if no error, otherwise error

4
storage/innobase/include/trx0trx.ic

@ -28,9 +28,9 @@ Created 3/26/1996 Heikki Tuuri
/**********************************************************************//**
Determines if a transaction is in the given state.
The caller must hold trx_sys->mutex, or it must be the thread
The caller must hold trx_sys.mutex, or it must be the thread
that is serving a running transaction.
A running RW transaction must be in trx_sys->rw_trx_hash.
A running RW transaction must be in trx_sys.rw_trx_hash.
@return TRUE if trx->state == state */
UNIV_INLINE
bool

66
storage/innobase/lock/lock0lock.cc

@ -354,7 +354,7 @@ lock_report_trx_id_insanity(
const rec_t* rec, /*!< in: user record */
dict_index_t* index, /*!< in: index */
const ulint* offsets, /*!< in: rec_get_offsets(rec, index) */
trx_id_t max_trx_id) /*!< in: trx_sys->get_max_trx_id() */
trx_id_t max_trx_id) /*!< in: trx_sys.get_max_trx_id() */
{
ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(!rec_is_default_row(rec, index));
@ -382,7 +382,7 @@ lock_check_trx_id_sanity(
ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(!rec_is_default_row(rec, index));
trx_id_t max_trx_id = trx_sys->get_max_trx_id();
trx_id_t max_trx_id = trx_sys.get_max_trx_id();
if (trx_id >= max_trx_id) {
lock_report_trx_id_insanity(
@ -1494,7 +1494,7 @@ lock_sec_rec_some_has_impl(
const page_t* page = page_align(rec);
ut_ad(!lock_mutex_own());
ut_ad(!trx_sys_mutex_own());
ut_ad(!mutex_own(&trx_sys.mutex));
ut_ad(!dict_index_is_clust(index));
ut_ad(page_rec_is_user_rec(rec));
ut_ad(rec_offs_validate(rec, index, offsets));
@ -1508,7 +1508,7 @@ lock_sec_rec_some_has_impl(
max trx id to the log, and therefore during recovery, this value
for a page may be incorrect. */
if (max_trx_id < trx_sys->get_min_trx_id()) {
if (max_trx_id < trx_sys.get_min_trx_id()) {
trx = 0;
@ -5209,7 +5209,7 @@ lock_release(
{
lock_t* lock;
ulint count = 0;
trx_id_t max_trx_id = trx_sys->get_max_trx_id();
trx_id_t max_trx_id = trx_sys.get_max_trx_id();
ut_ad(lock_mutex_own());
ut_ad(!trx_mutex_own(trx));
@ -5633,7 +5633,7 @@ lock_print_info_summary(
"------------\n", file);
fprintf(file, "Trx id counter " TRX_ID_FMT "\n",
trx_sys->get_max_trx_id());
trx_sys.get_max_trx_id());
fprintf(file,
"Purge done for trx's n:o < " TRX_ID_FMT
@ -5674,8 +5674,7 @@ lock_print_info_summary(
fprintf(file, "\n");
fprintf(file,
"History list length %lu\n",
(ulong) trx_sys->rseg_history_len);
"History list length " ULINTPF "\n", trx_sys.rseg_history_len);
#ifdef PRINT_NUM_OF_LOCK_STRUCTS
fprintf(file,
@ -5694,7 +5693,7 @@ struct PrintNotStarted {
void operator()(const trx_t* trx)
{
ut_ad(trx->in_mysql_trx_list);
ut_ad(mutex_own(&trx_sys->mutex));
ut_ad(mutex_own(&trx_sys.mutex));
/* See state transitions and locking rules in trx0trx.h */
@ -5821,11 +5820,11 @@ lock_print_info_all_transactions(
available from INFORMATION_SCHEMA.INNODB_TRX. */
PrintNotStarted print_not_started(file);
mutex_enter(&trx_sys->mutex);
ut_list_map(trx_sys->mysql_trx_list, print_not_started);
mutex_exit(&trx_sys->mutex);
mutex_enter(&trx_sys.mutex);
ut_list_map(trx_sys.mysql_trx_list, print_not_started);
mutex_exit(&trx_sys.mutex);
trx_sys->rw_trx_hash.iterate_no_dups(
trx_sys.rw_trx_hash.iterate_no_dups(
reinterpret_cast<my_hash_walk_action>
(lock_print_info_all_transactions_callback), file);
lock_mutex_exit();
@ -5889,14 +5888,14 @@ lock_table_queue_validate(
const lock_t* lock;
ut_ad(lock_mutex_own());
ut_ad(trx_sys_mutex_own());
ut_ad(mutex_own(&trx_sys.mutex));
for (lock = UT_LIST_GET_FIRST(table->locks);
lock != NULL;
lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock)) {
/* lock->trx->state cannot change from or to NOT_STARTED
while we are holding the trx_sys->mutex. It may change
while we are holding the trx_sys.mutex. It may change
from ACTIVE to PREPARED, but it may not change to
COMMITTED, because we are holding the lock_sys->mutex. */
ut_ad(trx_assert_started(lock->trx));
@ -5949,7 +5948,7 @@ lock_rec_queue_validate(
if (!locked_lock_trx_sys) {
lock_mutex_enter();
mutex_enter(&trx_sys->mutex);
mutex_enter(&trx_sys.mutex);
}
if (!page_rec_is_user_rec(rec)) {
@ -5981,7 +5980,7 @@ lock_rec_queue_validate(
/* Unlike the non-debug code, this invariant can only succeed
if the check and assertion are covered by the lock mutex. */
const trx_t *impl_trx = trx_sys->rw_trx_hash.find(
const trx_t *impl_trx = trx_sys.rw_trx_hash.find(
lock_clust_rec_some_has_impl(rec, index, offsets));
ut_ad(lock_mutex_own());
@ -6081,7 +6080,7 @@ lock_rec_queue_validate(
func_exit:
if (!locked_lock_trx_sys) {
lock_mutex_exit();
mutex_exit(&trx_sys->mutex);
mutex_exit(&trx_sys.mutex);
}
return(TRUE);
@ -6109,7 +6108,7 @@ lock_rec_validate_page(
ut_ad(!lock_mutex_own());
lock_mutex_enter();
mutex_enter(&trx_sys->mutex);
mutex_enter(&trx_sys.mutex);
loop:
lock = lock_rec_get_first_on_page_addr(
lock_sys->rec_hash,
@ -6167,7 +6166,7 @@ loop:
function_exit:
lock_mutex_exit();
mutex_exit(&trx_sys->mutex);
mutex_exit(&trx_sys.mutex);
if (heap != NULL) {
mem_heap_free(heap);
@ -6188,7 +6187,7 @@ lock_rec_validate(
(space, page_no) */
{
ut_ad(lock_mutex_own());
ut_ad(trx_sys_mutex_own());
ut_ad(mutex_own(&trx_sys.mutex));
for (const lock_t* lock = static_cast<const lock_t*>(
HASH_GET_FIRST(lock_sys->rec_hash, start));
@ -6267,7 +6266,7 @@ static my_bool lock_validate_table_locks(rw_trx_hash_element_t *element,
void *arg)
{
ut_ad(lock_mutex_own());
ut_ad(trx_sys_mutex_own()); /* Do we really need this. */
ut_ad(mutex_own(&trx_sys.mutex)); /* Do we really need this. */
mutex_enter(&element->mutex);
if (element->trx)
{
@ -6302,11 +6301,11 @@ lock_validate()
page_addr_set pages;
lock_mutex_enter();
mutex_enter(&trx_sys->mutex);
mutex_enter(&trx_sys.mutex);
/* Validate table locks */
trx_sys->rw_trx_hash.iterate(reinterpret_cast<my_hash_walk_action>
(lock_validate_table_locks), 0);
trx_sys.rw_trx_hash.iterate(reinterpret_cast<my_hash_walk_action>
(lock_validate_table_locks), 0);
/* Iterate over all the record locks and validate the locks. We
don't want to hog the lock_sys_t::mutex and the trx_sys_t::mutex.
@ -6325,7 +6324,7 @@ lock_validate()
}
}
mutex_exit(&trx_sys->mutex);
mutex_exit(&trx_sys.mutex);
lock_mutex_exit();
for (page_addr_set::const_iterator it = pages.begin();
@ -6589,10 +6588,10 @@ static void lock_rec_other_trx_holds_expl(trx_t *caller_trx, trx_t *trx,
lock_mutex_enter();
lock_rec_other_trx_holds_expl_arg arg= { page_rec_get_heap_no(rec), block,
trx };
trx_sys->rw_trx_hash.iterate(caller_trx,
reinterpret_cast<my_hash_walk_action>
(lock_rec_other_trx_holds_expl_callback),
&arg);
trx_sys.rw_trx_hash.iterate(caller_trx,
reinterpret_cast<my_hash_walk_action>
(lock_rec_other_trx_holds_expl_callback),
&arg);
lock_mutex_exit();
}
}
@ -6626,7 +6625,7 @@ lock_rec_convert_impl_to_expl(
trx_id = lock_clust_rec_some_has_impl(rec, index, offsets);
trx = trx_sys->rw_trx_hash.find(caller_trx, trx_id, true);
trx = trx_sys.rw_trx_hash.find(caller_trx, trx_id, true);
} else {
ut_ad(!dict_index_is_online_ddl(index));
@ -6855,8 +6854,7 @@ lock_sec_rec_read_check_and_lock(
database recovery is running. */
if (!page_rec_is_supremum(rec)
&& page_get_max_trx_id(block->frame) >=
trx_sys->get_min_trx_id()) {
&& page_get_max_trx_id(block->frame) >= trx_sys.get_min_trx_id()) {
lock_rec_convert_impl_to_expl(thr_get_trx(thr), block, rec,
index, offsets);
@ -7586,7 +7584,7 @@ lock_table_has_locks(
#ifdef UNIV_DEBUG
if (!has_locks) {
trx_sys->rw_trx_hash.iterate(
trx_sys.rw_trx_hash.iterate(
reinterpret_cast<my_hash_walk_action>
(lock_table_locks_lookup),
const_cast<dict_table_t*>(table));

2
storage/innobase/log/log0log.cc

@ -1918,7 +1918,7 @@ loop:
if (ulint total_trx = srv_was_started && !srv_read_only_mode
&& srv_force_recovery < SRV_FORCE_NO_TRX_UNDO
? trx_sys_any_active_transactions() : 0) {
? trx_sys.any_active_transactions() : 0) {
if (srv_print_verbose_log && count > 600) {
ib::info() << "Waiting for " << total_trx << " active"

2
storage/innobase/page/page0page.cc

@ -2432,7 +2432,7 @@ page_validate(
&& page_is_leaf(page)
&& !page_is_empty(page)) {
trx_id_t max_trx_id = page_get_max_trx_id(page);
trx_id_t sys_max_trx_id = trx_sys->get_max_trx_id();
trx_id_t sys_max_trx_id = trx_sys.get_max_trx_id();
if (max_trx_id == 0 || max_trx_id > sys_max_trx_id) {
ib::error() << "PAGE_MAX_TRX_ID out of bounds: "

61
storage/innobase/read/read0read.cc

@ -162,8 +162,8 @@ For details see: row_vers_old_has_index_entry() and row_purge_poss_sec()
Some additional issues:
What if trx_sys->view_list == NULL and some transaction T1 and Purge both
try to open read_view at same time. Only one can acquire trx_sys->mutex.
What if trx_sys.view_list == NULL and some transaction T1 and Purge both
try to open read_view at same time. Only one can acquire trx_sys.mutex.
In which order will the views be opened? Should it matter? If no, why?
The order does not matter. No new transactions can be created and no running
@ -200,7 +200,7 @@ MVCC::validate() const
{
ViewCheck check;
ut_ad(mutex_own(&trx_sys->mutex));
ut_ad(mutex_own(&trx_sys.mutex));
ut_list_map(m_views, check);
@ -371,7 +371,7 @@ Copy the transaction ids from the source vector */
void
ReadView::copy_trx_ids(const trx_ids_t& trx_ids)
{
ut_ad(mutex_own(&trx_sys->mutex));
ut_ad(mutex_own(&trx_sys.mutex));
ulint size = trx_ids.size();
if (m_creator_trx_id > 0) {
@ -438,11 +438,11 @@ ReadView::copy_trx_ids(const trx_ids_t& trx_ids)
Now rw_trx_ids and rw_trx_hash may get out of sync for a short while:
when transaction is registered it first gets added into rw_trx_ids
under trx_sys->mutex protection and then to rw_trx_hash without mutex
under trx_sys.mutex protection and then to rw_trx_hash without mutex
protection. Thus we need repeat this lookup. */
for (trx_ids_t::const_iterator it = trx_ids.begin();
it != trx_ids.end(); ++it) {
while (!trx_sys->rw_trx_hash.find(*it));
while (!trx_sys.rw_trx_hash.find(*it));
}
#endif /* UNIV_DEBUG */
}
@ -455,22 +455,22 @@ point in time are seen in the view.
void
ReadView::prepare(trx_id_t id)
{
ut_ad(mutex_own(&trx_sys->mutex));
ut_ad(mutex_own(&trx_sys.mutex));
m_creator_trx_id = id;
m_low_limit_no = m_low_limit_id = trx_sys->get_max_trx_id();
m_low_limit_no = m_low_limit_id = trx_sys.get_max_trx_id();
if (!trx_sys->rw_trx_ids.empty()) {
copy_trx_ids(trx_sys->rw_trx_ids);
if (!trx_sys.rw_trx_ids.empty()) {
copy_trx_ids(trx_sys.rw_trx_ids);
} else {
m_ids.clear();
}
if (UT_LIST_GET_LEN(trx_sys->serialisation_list) > 0) {
if (UT_LIST_GET_LEN(trx_sys.serialisation_list) > 0) {
const trx_t* trx;
trx = UT_LIST_GET_FIRST(trx_sys->serialisation_list);
trx = UT_LIST_GET_FIRST(trx_sys.serialisation_list);
if (trx->no < m_low_limit_no) {
m_low_limit_no = trx->no;
@ -500,7 +500,7 @@ a new view.
ReadView*
MVCC::get_view()
{
ut_ad(mutex_own(&trx_sys->mutex));
ut_ad(mutex_own(&trx_sys.mutex));
ReadView* view;
@ -526,7 +526,7 @@ void
MVCC::view_release(ReadView*& view)
{
ut_ad(!srv_read_only_mode);
ut_ad(trx_sys_mutex_own());
ut_ad(mutex_own(&trx_sys.mutex));
uintptr_t p = reinterpret_cast<uintptr_t>(view);
@ -537,7 +537,7 @@ MVCC::view_release(ReadView*& view)
ut_ad(view->m_closed);
/** RW transactions should not free their views here. Their views
should freed using view_close_view() */
should freed using view_close() */
ut_ad(view->m_creator_trx_id == 0);
@ -580,19 +580,19 @@ MVCC::view_open(ReadView*& view, trx_t* trx)
view->m_closed = false;
if (view->m_low_limit_id == trx_sys->get_max_trx_id()) {
if (view->m_low_limit_id == trx_sys.get_max_trx_id()) {
return;
} else {
view->m_closed = true;
}
}
mutex_enter(&trx_sys->mutex);
mutex_enter(&trx_sys.mutex);
UT_LIST_REMOVE(m_views, view);
} else {
mutex_enter(&trx_sys->mutex);
mutex_enter(&trx_sys.mutex);
view = get_view();
}
@ -610,7 +610,7 @@ MVCC::view_open(ReadView*& view, trx_t* trx)
ut_ad(validate());
}
trx_sys_mutex_exit();
mutex_exit(&trx_sys.mutex);
}
/**
@ -622,7 +622,7 @@ MVCC::get_oldest_view() const
{
ReadView* view;
ut_ad(mutex_own(&trx_sys->mutex));
ut_ad(mutex_own(&trx_sys.mutex));
for (view = UT_LIST_GET_LAST(m_views);
view != NULL;
@ -669,7 +669,7 @@ m_ids too and adjust the m_up_limit_id, if required */
void
ReadView::copy_complete()
{
ut_ad(!trx_sys_mutex_own());
ut_ad(!mutex_own(&trx_sys.mutex));
if (m_creator_trx_id > 0) {
m_ids.insert(m_creator_trx_id);
@ -695,23 +695,17 @@ purge the delete marked record or not.
void
MVCC::clone_oldest_view(ReadView* view)
{
mutex_enter(&trx_sys->mutex);
mutex_enter(&trx_sys.mutex);
ReadView* oldest_view = get_oldest_view();
if (oldest_view == NULL) {
view->prepare(0);
trx_sys_mutex_exit();
mutex_exit(&trx_sys.mutex);
view->complete();
} else {
view->copy_prepare(*oldest_view);
trx_sys_mutex_exit();
mutex_exit(&trx_sys.mutex);
view->copy_complete();
}
}
@ -722,7 +716,7 @@ MVCC::clone_oldest_view(ReadView* view)
ulint
MVCC::size() const
{
trx_sys_mutex_enter();
mutex_enter(&trx_sys.mutex);
ulint size = 0;
@ -735,7 +729,7 @@ MVCC::size() const
}
}
trx_sys_mutex_exit();
mutex_exit(&trx_sys.mutex);
return(size);
}
@ -786,7 +780,6 @@ void
MVCC::set_view_creator_trx_id(ReadView* view, trx_id_t id)
{
ut_ad(id > 0);
ut_ad(mutex_own(&trx_sys->mutex));
ut_ad(mutex_own(&trx_sys.mutex));
view->creator_trx_id(id);
}

2
storage/innobase/row/row0purge.cc

@ -821,7 +821,7 @@ skip_secondaries:
&is_insert, &rseg_id,
&page_no, &offset);
rseg = trx_sys->rseg_array[rseg_id];
rseg = trx_sys.rseg_array[rseg_id];
ut_a(rseg != NULL);
ut_ad(rseg->id == rseg_id);

6
storage/innobase/row/row0row.cc

@ -396,7 +396,7 @@ row_build_low(
ut_ad(rec != NULL);
ut_ad(heap != NULL);
ut_ad(dict_index_is_clust(index));
ut_ad(!trx_sys_mutex_own());
ut_ad(!mutex_own(&trx_sys.mutex));
ut_ad(!col_map || col_table);
if (!offsets) {
@ -415,8 +415,8 @@ row_build_low(
times, and the cursor restore can happen multiple times for single
insert or update statement. */
ut_a(!rec_offs_any_null_extern(rec, offsets)
|| trx_sys->rw_trx_hash.find(row_get_rec_trx_id(rec, index,
offsets)));
|| trx_sys.rw_trx_hash.find(row_get_rec_trx_id(rec, index,
offsets)));
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
if (type != ROW_COPY_POINTERS) {

4
storage/innobase/row/row0sel.cc

@ -4876,7 +4876,7 @@ wrong_offs:
/* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */
ut_ad(trx_id);
if (!trx_sys->rw_trx_hash.find(trx, trx_id)) {
if (!trx_sys.rw_trx_hash.find(trx, trx_id)) {
/* The clustered index record
was delete-marked in a committed
transaction. Ignore the record. */
@ -5888,7 +5888,7 @@ row_search_check_if_query_cache_permitted(
&& !srv_read_only_mode
&& !MVCC::is_view_active(trx->read_view)) {
trx_sys->mvcc->view_open(trx->read_view, trx);
trx_sys.mvcc->view_open(trx->read_view, trx);
}
}

8
storage/innobase/row/row0vers.cc

@ -121,7 +121,7 @@ row_vers_impl_x_locked_low(
DBUG_RETURN(0);
}
trx_t* trx = trx_sys->rw_trx_hash.find(caller_trx, trx_id, true);
trx_t* trx = trx_sys.rw_trx_hash.find(caller_trx, trx_id, true);
if (trx == 0) {
/* The transaction that modified or inserted clust_rec is no
@ -186,7 +186,7 @@ row_vers_impl_x_locked_low(
inserting a delete-marked record. */
ut_ad(prev_version
|| !rec_get_deleted_flag(version, comp)
|| !trx_sys->rw_trx_hash.find(caller_trx, trx_id));
|| !trx_sys.rw_trx_hash.find(caller_trx, trx_id));
/* Free version and clust_offsets. */
mem_heap_free(old_heap);
@ -358,7 +358,7 @@ row_vers_impl_x_locked(
dict_index_t* clust_index;
ut_ad(!lock_mutex_own());
ut_ad(!trx_sys_mutex_own());
ut_ad(!mutex_own(&trx_sys.mutex));
mtr_start(&mtr);
@ -1280,7 +1280,7 @@ row_vers_build_for_semi_consistent_read(
rec_trx_id = version_trx_id;
}
if (!trx_sys->rw_trx_hash.find(caller_trx, version_trx_id)) {
if (!trx_sys.rw_trx_hash.find(caller_trx, version_trx_id)) {
committed_version_trx:
/* We found a version that belongs to a
committed transaction: return it. */

4
storage/innobase/srv/srv0mon.cc

@ -1596,7 +1596,7 @@ srv_mon_get_rseg_size(void)
total rollback segment size and to avoid mutex contention we
don't acquire the rseg->mutex" */
for (i = 0; i < TRX_SYS_N_RSEGS; ++i) {
const trx_rseg_t* rseg = trx_sys->rseg_array[i];
const trx_rseg_t* rseg = trx_sys.rseg_array[i];
if (rseg != NULL) {
value += rseg->curr_size;
@ -1952,7 +1952,7 @@ srv_mon_process_existing_counter(
break;
case MONITOR_RSEG_HISTORY_LEN:
value = trx_sys->rseg_history_len;
value = trx_sys.rseg_history_len;
break;
case MONITOR_RSEG_CUR_SIZE:

26
storage/innobase/srv/srv0srv.cc

@ -1365,9 +1365,9 @@ srv_printf_innodb_monitor(
srv_conc_get_active_threads(),
srv_conc_get_waiting_threads());
/* This is a dirty read, without holding trx_sys->mutex. */
/* This is a dirty read, without holding trx_sys.mutex. */
fprintf(file, ULINTPF " read views open inside InnoDB\n",
trx_sys->mvcc->size());
trx_sys.mvcc->size());
n_reserved = fil_space_get_n_reserved_extents(0);
if (n_reserved > 0) {
@ -1638,9 +1638,9 @@ srv_export_innodb_status(void)
trx_id_t done_trx_no = purge_sys->done.trx_no;
rw_lock_s_unlock(&purge_sys->latch);
mutex_enter(&trx_sys->mutex);
trx_id_t max_trx_id = trx_sys->rw_max_trx_id;
mutex_exit(&trx_sys->mutex);
mutex_enter(&trx_sys.mutex);
trx_id_t max_trx_id = trx_sys.rw_max_trx_id;
mutex_exit(&trx_sys.mutex);
if (!done_trx_no || max_trx_id < done_trx_no - 1) {
export_vars.innodb_purge_trx_id_age = 0;
@ -2006,7 +2006,7 @@ srv_wake_purge_thread_if_not_active()
if (purge_sys->state == PURGE_STATE_RUN
&& !my_atomic_loadlint(&srv_sys.n_threads_active[SRV_PURGE])
&& my_atomic_loadlint(&trx_sys->rseg_history_len)) {
&& my_atomic_loadlint(&trx_sys.rseg_history_len)) {
srv_release_threads(SRV_PURGE, 1);
}
@ -2503,7 +2503,7 @@ srv_purge_should_exit(ulint n_purged)
return(false);
}
/* Exit if there are no active transactions to roll back. */
return(trx_sys_any_active_transactions() == 0);
return(trx_sys.any_active_transactions() == 0);
}
/*********************************************************************//**
@ -2645,7 +2645,7 @@ srv_do_purge(ulint* n_total_purged)
}
do {
if (trx_sys->rseg_history_len > rseg_history_len
if (trx_sys.rseg_history_len > rseg_history_len
|| (srv_max_purge_lag > 0
&& rseg_history_len > srv_max_purge_lag)) {
@ -2674,7 +2674,7 @@ srv_do_purge(ulint* n_total_purged)
ut_a(n_use_threads <= n_threads);
/* Take a snapshot of the history list before purge. */
if ((rseg_history_len = trx_sys->rseg_history_len) == 0) {
if ((rseg_history_len = trx_sys.rseg_history_len) == 0) {
break;
}
@ -2729,7 +2729,7 @@ srv_purge_coordinator_suspend(
/* We don't wait right away on the the non-timed wait because
we want to signal the thread that wants to suspend purge. */
const bool wait = stop
|| rseg_history_len <= trx_sys->rseg_history_len;
|| rseg_history_len <= trx_sys.rseg_history_len;
const bool timeout = srv_resume_thread(
slot, sig_count, wait,
stop ? 0 : SRV_PURGE_MAX_TIMEOUT);
@ -2746,8 +2746,8 @@ srv_purge_coordinator_suspend(
purge_sys->running = true;
if (timeout
&& rseg_history_len == trx_sys->rseg_history_len
&& trx_sys->rseg_history_len < 5000) {
&& rseg_history_len == trx_sys.rseg_history_len
&& trx_sys.rseg_history_len < 5000) {
/* No new records were added since the
wait started. Simply wait for new
records. The magic number 5000 is an
@ -2808,7 +2808,7 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
slot = srv_reserve_slot(SRV_PURGE);
ulint rseg_history_len = trx_sys->rseg_history_len;
ulint rseg_history_len = trx_sys.rseg_history_len;
do {
/* If there are no records to purge or the last

8
storage/innobase/srv/srv0start.cc

@ -2141,7 +2141,7 @@ files_checked:
dict_stats_thread_init();
}
trx_sys_create();
trx_sys.create();
if (create_new_db) {
ut_a(!srv_read_only_mode);
@ -2835,7 +2835,7 @@ innodb_shutdown()
ut_ad(dict_stats_event || !srv_was_started || srv_read_only_mode);
ut_ad(dict_sys || !srv_was_started);
ut_ad(trx_sys || !srv_was_started);
ut_ad(trx_sys.mvcc || !srv_was_started);
ut_ad(buf_dblwr || !srv_was_started || srv_read_only_mode
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
ut_ad(lock_sys || !srv_was_started);
@ -2873,9 +2873,7 @@ innodb_shutdown()
if (log_sys) {
log_shutdown();
}
if (trx_sys) {
trx_sys_close();
}
trx_sys.close();
UT_DELETE(purge_sys);
purge_sys = NULL;
if (buf_dblwr) {

13
storage/innobase/trx/trx0i_s.cc

@ -172,7 +172,7 @@ struct trx_i_s_cache_t {
ha_storage_t* storage; /*!< storage for external volatile
data that may become unavailable
when we release
lock_sys->mutex or trx_sys->mutex */
lock_sys->mutex or trx_sys.mutex */
ulint mem_allocd; /*!< the amount of memory
allocated with mem_alloc*() */
ibool is_truncated; /*!< this is TRUE if the memory
@ -1300,13 +1300,12 @@ static void fetch_data_into_cache(trx_i_s_cache_t *cache)
Capture the state of the read-write transactions. This includes
internal transactions too. They are not on mysql_trx_list
*/
trx_sys->rw_trx_hash.iterate_no_dups(reinterpret_cast<my_hash_walk_action>
(fetch_data_into_cache_callback),
cache);
trx_sys.rw_trx_hash.iterate_no_dups(reinterpret_cast<my_hash_walk_action>
(fetch_data_into_cache_callback), cache);
/* Capture the state of the read-only active transactions */
trx_sys_mutex_enter();
for (const trx_t *trx= UT_LIST_GET_FIRST(trx_sys->mysql_trx_list);
mutex_enter(&trx_sys.mutex);
for (const trx_t *trx= UT_LIST_GET_FIRST(trx_sys.mysql_trx_list);
trx != NULL;
trx= UT_LIST_GET_NEXT(mysql_trx_list, trx))
{
@ -1321,7 +1320,7 @@ static void fetch_data_into_cache(trx_i_s_cache_t *cache)
break;
}
}
trx_sys_mutex_exit();
mutex_exit(&trx_sys.mutex);
cache->is_truncated= FALSE;
}

14
storage/innobase/trx/trx0purge.cc

@ -312,7 +312,7 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
flst_add_first(rseg_header + TRX_RSEG_HISTORY,
undo_header + TRX_UNDO_HISTORY_NODE, mtr);
my_atomic_addlint(&trx_sys->rseg_history_len, 1);
my_atomic_addlint(&trx_sys.rseg_history_len, 1);
mlog_write_ull(undo_header + TRX_UNDO_TRX_NO, trx->no, mtr);
/* This is needed for upgrading old undo log pages from
@ -354,7 +354,7 @@ trx_purge_remove_log_hdr(
{
flst_remove(rseg_hdr + TRX_RSEG_HISTORY,
log_hdr + TRX_UNDO_HISTORY_NODE, mtr);
my_atomic_addlint(&trx_sys->rseg_history_len, -1);
my_atomic_addlint(&trx_sys.rseg_history_len, -1);
}
/** Free an undo log segment, and remove the header from the history list.
@ -847,7 +847,7 @@ trx_purge_mark_undo_for_truncate(
/* Step-3: Iterate over all the rsegs of selected UNDO tablespace
and mark them temporarily unavailable for allocation.*/
for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) {
if (trx_rseg_t* rseg = trx_sys->rseg_array[i]) {
if (trx_rseg_t* rseg = trx_sys.rseg_array[i]) {
ut_ad(rseg->is_persistent());
if (rseg->space == undo_trunc->get_marked_space_id()) {
@ -1087,7 +1087,7 @@ trx_purge_truncate_history(
ut_ad(limit->trx_no <= purge_sys->view.low_limit_no());
for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) {
trx_rseg_t* rseg = trx_sys->rseg_array[i];
trx_rseg_t* rseg = trx_sys.rseg_array[i];
if (rseg != NULL) {
ut_a(rseg->id == i);
@ -1524,12 +1524,12 @@ trx_purge_dml_delay(void)
/* If purge lag is set (ie. > 0) then calculate the new DML delay.
Note: we do a dirty read of the trx_sys_t data structure here,
without holding trx_sys->mutex. */
without holding trx_sys.mutex. */
if (srv_max_purge_lag > 0) {
float ratio;
ratio = float(trx_sys->rseg_history_len) / srv_max_purge_lag;
ratio = float(trx_sys.rseg_history_len) / srv_max_purge_lag;
if (ratio > 1.0) {
/* If the history list length exceeds the
@ -1600,7 +1600,7 @@ trx_purge(
ut_a(purge_sys->n_submitted == purge_sys->n_completed);
rw_lock_x_lock(&purge_sys->latch);
trx_sys->mvcc->clone_oldest_view(&purge_sys->view);
trx_sys.mvcc->clone_oldest_view(&purge_sys->view);
rw_lock_x_unlock(&purge_sys->latch);
#ifdef UNIV_DEBUG

4
storage/innobase/trx/trx0rec.cc

@ -2192,8 +2192,8 @@ trx_undo_get_undo_rec_low(
trx_undo_decode_roll_ptr(roll_ptr, &is_insert, &rseg_id, &page_no,
&offset);
rseg = is_temp
? trx_sys->temp_rsegs[rseg_id]
: trx_sys->rseg_array[rseg_id];
? trx_sys.temp_rsegs[rseg_id]
: trx_sys.rseg_array[rseg_id];
ut_ad(is_temp == !rseg->is_persistent());
mtr_start(&mtr);

17
storage/innobase/trx/trx0roll.cc

@ -198,7 +198,7 @@ dberr_t
trx_rollback_low(
trx_t* trx)
{
/* We are reading trx->state without holding trx_sys->mutex
/* We are reading trx->state without holding trx_sys.mutex
here, because the rollback should be invoked for a running
active MySQL transaction (or recovered prepared transaction)
that is associated with the current thread. */
@ -306,7 +306,7 @@ trx_rollback_last_sql_stat_for_mysql(
{
dberr_t err;
/* We are reading trx->state without holding trx_sys->mutex
/* We are reading trx->state without holding trx_sys.mutex
here, because the statement rollback should be invoked for a
running active MySQL transaction that is associated with the
current thread. */
@ -486,7 +486,7 @@ trx_rollback_to_savepoint_for_mysql(
{
trx_named_savept_t* savep;
/* We are reading trx->state without holding trx_sys->mutex
/* We are reading trx->state without holding trx_sys.mutex
here, because the savepoint rollback should be invoked for a
running active MySQL transaction that is associated with the
current thread. */
@ -774,7 +774,7 @@ trx_roll_must_shutdown()
/* Get number of recovered active transactions and number of
rows they modified. Numbers must be accurate, because only this
thread is allowed to touch recovered transactions. */
trx_sys->rw_trx_hash.iterate_no_dups(
trx_sys.rw_trx_hash.iterate_no_dups(
reinterpret_cast<my_hash_walk_action>
(trx_roll_count_callback), &arg);
ib::info() << "To roll back: " << arg.n_trx
@ -831,8 +831,9 @@ void trx_rollback_recovered(bool all)
other thread is allowed to modify or remove these transactions from
rw_trx_hash.
*/
trx_sys->rw_trx_hash.iterate_no_dups(reinterpret_cast<my_hash_walk_action>
(trx_rollback_recovered_callback), &trx_list);
trx_sys.rw_trx_hash.iterate_no_dups(reinterpret_cast<my_hash_walk_action>
(trx_rollback_recovered_callback),
&trx_list);
while (trx_t *trx= UT_LIST_GET_FIRST(trx_list))
{
@ -858,7 +859,7 @@ void trx_rollback_recovered(bool all)
ut_ad(!srv_undo_sources);
ut_ad(srv_fast_shutdown);
discard:
trx_sys->rw_trx_hash.erase(trx);
trx_sys.rw_trx_hash.erase(trx);
trx_free_at_shutdown(trx);
}
else
@ -886,7 +887,7 @@ DECLARE_THREAD(trx_rollback_all_recovered)(void*)
pfs_register_thread(trx_rollback_clean_thread_key);
#endif /* UNIV_PFS_THREAD */
if (trx_sys->rw_trx_hash.size()) {
if (trx_sys.rw_trx_hash.size()) {
ib::info() << "Starting in background the rollback of"
" recovered transactions";
trx_rollback_recovered(true);

16
storage/innobase/trx/trx0rseg.cc

@ -190,7 +190,7 @@ trx_rseg_mem_restore(trx_rseg_t* rseg, mtr_t* mtr)
len = flst_get_len(rseg_header + TRX_RSEG_HISTORY);
if (len > 0) {
my_atomic_addlint(&trx_sys->rseg_history_len, len);
my_atomic_addlint(&trx_sys.rseg_history_len, len);
node_addr = trx_purge_get_log_from_hist(
flst_get_last(rseg_header + TRX_RSEG_HISTORY, mtr));
@ -240,8 +240,8 @@ trx_rseg_array_init()
trx_sysf_rseg_get_space(sys_header, i, &mtr),
page_no);
ut_ad(rseg->is_persistent());
ut_ad(!trx_sys->rseg_array[rseg->id]);
trx_sys->rseg_array[rseg->id] = rseg;
ut_ad(!trx_sys.rseg_array[rseg->id]);
trx_sys.rseg_array[rseg->id] = rseg;
trx_rseg_mem_restore(rseg, &mtr);
}
@ -262,7 +262,7 @@ trx_rseg_create(ulint space_id)
mtr.start();
/* To obey the latching order, acquire the file space
x-latch before the trx_sys->mutex. */
x-latch before the trx_sys.mutex. */
#ifdef UNIV_DEBUG
const fil_space_t* space =
#endif /* UNIV_DEBUG */
@ -283,8 +283,8 @@ trx_rseg_create(ulint space_id)
rseg = trx_rseg_mem_create(slot_no, space_id, page_no);
ut_ad(rseg->is_persistent());
ut_ad(!trx_sys->rseg_array[rseg->id]);
trx_sys->rseg_array[rseg->id] = rseg;
ut_ad(!trx_sys.rseg_array[rseg->id]);
trx_sys.rseg_array[rseg->id] = rseg;
trx_rseg_mem_restore(rseg, &mtr);
}
@ -313,8 +313,8 @@ trx_temp_rseg_create()
trx_rseg_t* rseg = trx_rseg_mem_create(
i, SRV_TMP_SPACE_ID, page_no);
ut_ad(!rseg->is_persistent());
ut_ad(!trx_sys->temp_rsegs[i]);
trx_sys->temp_rsegs[i] = rseg;
ut_ad(!trx_sys.temp_rsegs[i]);
trx_sys.temp_rsegs[i] = rseg;
trx_rseg_mem_restore(rseg, &mtr);
mtr.commit();
}

89
storage/innobase/trx/trx0sys.cc

@ -48,7 +48,7 @@ Created 3/26/1996 Heikki Tuuri
#include <mysql/service_wsrep.h>
/** The transaction system */
trx_sys_t* trx_sys;
trx_sys_t trx_sys;
/** Check whether transaction id is valid.
@param[in] id transaction id to check
@ -58,7 +58,7 @@ ReadView::check_trx_id_sanity(
trx_id_t id,
const table_name_t& name)
{
if (id >= trx_sys->get_max_trx_id()) {
if (id >= trx_sys.get_max_trx_id()) {
ib::warn() << "A transaction id"
<< " in a record of table "
@ -96,13 +96,13 @@ uint trx_rseg_n_slots_debug = 0;
void trx_sys_t::flush_max_trx_id()
{
ut_ad(trx_sys->mutex.is_owned());
ut_ad(trx_sys.mutex.is_owned());
if (!srv_read_only_mode)
{
mtr_t mtr;
mtr.start();
mlog_write_ull(trx_sysf_get(&mtr) + TRX_SYS_TRX_ID_STORE,
trx_sys->get_max_trx_id(), &mtr);
trx_sys.get_max_trx_id(), &mtr);
mtr.commit();
}
}
@ -424,7 +424,7 @@ trx_sys_init_at_db_start()
/* VERY important: after the database is started, max_trx_id value is
divisible by TRX_SYS_TRX_ID_WRITE_MARGIN, and the 'if' in
trx_sys->get_new_trx_id will evaluate to TRUE when the function
trx_sys.get_new_trx_id will evaluate to TRUE when the function
is first time called, and the value for trx id will be written
to the disk-based header! Thus trx id values will not overlap when
the database is repeatedly started! */
@ -434,40 +434,34 @@ trx_sys_init_at_db_start()
sys_header = trx_sysf_get(&mtr);
trx_sys->init_max_trx_id(2 * TRX_SYS_TRX_ID_WRITE_MARGIN
trx_sys.init_max_trx_id(2 * TRX_SYS_TRX_ID_WRITE_MARGIN
+ ut_uint64_align_up(mach_read_from_8(sys_header
+ TRX_SYS_TRX_ID_STORE),
TRX_SYS_TRX_ID_WRITE_MARGIN));
mtr.commit();
ut_d(trx_sys->rw_max_trx_id = trx_sys->get_max_trx_id());
ut_d(trx_sys.rw_max_trx_id = trx_sys.get_max_trx_id());
trx_dummy_sess = sess_open();
trx_lists_init_at_db_start();
trx_sys->mvcc->clone_oldest_view(&purge_sys->view);
trx_sys.mvcc->clone_oldest_view(&purge_sys->view);
}
/*****************************************************************//**
Creates the trx_sys instance and initializes purge_queue and mutex. */
/** Create the instance */
void
trx_sys_create(void)
/*================*/
trx_sys_t::create()
{
ut_ad(trx_sys == NULL);
trx_sys = static_cast<trx_sys_t*>(ut_zalloc_nokey(sizeof(*trx_sys)));
mutex_create(LATCH_ID_TRX_SYS, &trx_sys->mutex);
ut_ad(this == &trx_sys);
ut_ad(!mvcc);
mutex_create(LATCH_ID_TRX_SYS, &mutex);
UT_LIST_INIT(trx_sys->serialisation_list, &trx_t::no_list);
UT_LIST_INIT(trx_sys->mysql_trx_list, &trx_t::mysql_trx_list);
UT_LIST_INIT(serialisation_list, &trx_t::no_list);
UT_LIST_INIT(mysql_trx_list, &trx_t::mysql_trx_list);
trx_sys->mvcc = UT_NEW_NOKEY(MVCC(1024));
mvcc = UT_NEW_NOKEY(MVCC(1024));
new(&trx_sys->rw_trx_ids) trx_ids_t(ut_allocator<trx_id_t>(
mem_key_trx_sys_t_rw_trx_ids));
trx_sys->rw_trx_hash.init();
rw_trx_hash.init();
}
/*****************************************************************//**
@ -563,16 +557,16 @@ trx_sys_create_rsegs()
return(true);
}
/*********************************************************************
Shutdown/Close the transaction system. */
/** Close the transaction system on shutdown */
void
trx_sys_close(void)
/*===============*/
trx_sys_t::close()
{
ut_ad(trx_sys != NULL);
ut_ad(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS);
if (!mvcc) {
return;
}
if (ulint size = trx_sys->mvcc->size()) {
if (ulint size = mvcc->size()) {
ib::error() << "All read views were not closed before"
" shutdown: " << size << " read views open";
}
@ -582,33 +576,27 @@ trx_sys_close(void)
trx_dummy_sess = NULL;
}
trx_sys->rw_trx_hash.destroy();
rw_trx_hash.destroy();
/* There can't be any active transactions. */
for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) {
if (trx_rseg_t* rseg = trx_sys->rseg_array[i]) {
if (trx_rseg_t* rseg = rseg_array[i]) {
trx_rseg_mem_free(rseg);
}
if (trx_rseg_t* rseg = trx_sys->temp_rsegs[i]) {
if (trx_rseg_t* rseg = temp_rsegs[i]) {
trx_rseg_mem_free(rseg);
}
}
UT_DELETE(trx_sys->mvcc);
UT_DELETE(mvcc);
ut_a(UT_LIST_GET_LEN(trx_sys->mysql_trx_list) == 0);
ut_a(UT_LIST_GET_LEN(trx_sys->serialisation_list) == 0);
ut_a(UT_LIST_GET_LEN(mysql_trx_list) == 0);
ut_a(UT_LIST_GET_LEN(serialisation_list) == 0);
/* We used placement new to create this mutex. Call the destructor. */
mutex_free(&trx_sys->mutex);
trx_sys->rw_trx_ids.~trx_ids_t();
ut_free(trx_sys);
trx_sys = NULL;
mutex_free(&mutex);
}
@ -628,29 +616,24 @@ static my_bool active_count_callback(rw_trx_hash_element_t *element,
}
/*********************************************************************
Check if there are any active (non-prepared) transactions.
This is only used to check if it's safe to shutdown.
@return total number of active transactions or 0 if none */
ulint
trx_sys_any_active_transactions(void)
/*=================================*/
/** @return total number of active (non-prepared) transactions */
ulint trx_sys_t::any_active_transactions()
{
uint32_t total_trx = 0;
trx_sys->rw_trx_hash.iterate_no_dups(
trx_sys.rw_trx_hash.iterate_no_dups(
reinterpret_cast<my_hash_walk_action>
(active_count_callback), &total_trx);
trx_sys_mutex_enter();
for (trx_t* trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list);
mutex_enter(&trx_sys.mutex);
for (trx_t* trx = UT_LIST_GET_FIRST(trx_sys.mysql_trx_list);
trx != NULL;
trx = UT_LIST_GET_NEXT(mysql_trx_list, trx)) {
if (trx->state != TRX_STATE_NOT_STARTED && !trx->id) {
total_trx++;
}
}
trx_sys_mutex_exit();
mutex_exit(&trx_sys.mutex);
return(total_trx);
}

160
storage/innobase/trx/trx0trx.cc

@ -494,7 +494,7 @@ trx_free(trx_t*& trx)
{
assert_trx_is_free(trx);
trx_sys->rw_trx_hash.put_pins(trx);
trx_sys.rw_trx_hash.put_pins(trx);
trx->mysql_thd = 0;
trx->mysql_log_file_name = 0;
@ -546,12 +546,12 @@ trx_allocate_for_mysql(void)
trx = trx_allocate_for_background();
trx_sys_mutex_enter();
mutex_enter(&trx_sys.mutex);
ut_d(trx->in_mysql_trx_list = TRUE);
UT_LIST_ADD_FIRST(trx_sys->mysql_trx_list, trx);
UT_LIST_ADD_FIRST(trx_sys.mysql_trx_list, trx);
trx_sys_mutex_exit();
mutex_exit(&trx_sys.mutex);
return(trx);
}
@ -670,15 +670,15 @@ trx_disconnect_from_mysql(
trx_t* trx,
bool prepared)
{
trx_sys_mutex_enter();
mutex_enter(&trx_sys.mutex);
ut_ad(trx->in_mysql_trx_list);
ut_d(trx->in_mysql_trx_list = FALSE);
UT_LIST_REMOVE(trx_sys->mysql_trx_list, trx);
UT_LIST_REMOVE(trx_sys.mysql_trx_list, trx);
if (trx->read_view != NULL) {
trx_sys->mvcc->view_close(trx->read_view, true);
trx_sys.mvcc->view_close(trx->read_view, true);
}
if (prepared) {
@ -691,7 +691,7 @@ trx_disconnect_from_mysql(
trx->will_lock = 0;
}
trx_sys_mutex_exit();
mutex_exit(&trx_sys.mutex);
}
/** Disconnect a transaction from MySQL.
@ -817,7 +817,7 @@ static void trx_resurrect(trx_undo_t *undo, trx_rseg_t *rseg,
trx_state_t state;
/*
This is single-threaded startup code, we do not need the
protection of trx->mutex or trx_sys->mutex here.
protection of trx->mutex or trx_sys.mutex here.
*/
switch (undo->state)
{
@ -875,15 +875,15 @@ static void trx_resurrect(trx_undo_t *undo, trx_rseg_t *rseg,
trx->table_id= undo->table_id;
}
trx_sys->rw_trx_hash.insert(trx);
trx_sys->rw_trx_hash.put_pins(trx);
trx_sys->rw_trx_ids.push_back(trx->id);
trx_sys.rw_trx_hash.insert(trx);
trx_sys.rw_trx_hash.put_pins(trx);
trx_sys.rw_trx_ids.push_back(trx->id);
trx_resurrect_table_locks(trx, undo);
if (trx_state_eq(trx, TRX_STATE_ACTIVE))
*rows_to_undo+= trx->undo_no;
#ifdef UNIV_DEBUG
if (trx->id > trx_sys->rw_max_trx_id)
trx_sys->rw_max_trx_id= trx->id;
if (trx->id > trx_sys.rw_max_trx_id)
trx_sys.rw_max_trx_id= trx->id;
#endif
}
@ -909,7 +909,7 @@ trx_lists_init_at_db_start()
for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) {
trx_undo_t* undo;
trx_rseg_t* rseg = trx_sys->rseg_array[i];
trx_rseg_t* rseg = trx_sys.rseg_array[i];
/* At this stage non-redo rseg slots are all NULL as they are
re-created on server start and existing slots are not read. */
@ -931,7 +931,7 @@ trx_lists_init_at_db_start()
for (undo = UT_LIST_GET_FIRST(rseg->undo_list);
undo != NULL;
undo = UT_LIST_GET_NEXT(undo_list, undo)) {
trx_t *trx = trx_sys->rw_trx_hash.find(undo->trx_id);
trx_t *trx = trx_sys.rw_trx_hash.find(undo->trx_id);
if (!trx) {
trx_resurrect(undo, rseg, start_time,
&rows_to_undo, false);
@ -962,17 +962,17 @@ trx_lists_init_at_db_start()
}
}
if (trx_sys->rw_trx_hash.size()) {
if (trx_sys.rw_trx_hash.size()) {
ib::info() << trx_sys->rw_trx_hash.size()
ib::info() << trx_sys.rw_trx_hash.size()
<< " transaction(s) which must be rolled back or"
" cleaned up in total " << rows_to_undo
<< " row operations to undo";
ib::info() << "Trx id counter is " << trx_sys->get_max_trx_id();
ib::info() << "Trx id counter is " << trx_sys.get_max_trx_id();
}
std::sort(trx_sys->rw_trx_ids.begin(), trx_sys->rw_trx_ids.end());
std::sort(trx_sys.rw_trx_ids.begin(), trx_sys.rw_trx_ids.end());
}
/** Assign a persistent rollback segment in a round-robin fashion,
@ -989,7 +989,7 @@ trx_assign_rseg_low()
}
/* The first slot is always assigned to the system tablespace. */
ut_ad(trx_sys->rseg_array[0]->space == TRX_SYS_SPACE);
ut_ad(trx_sys.rseg_array[0]->space == TRX_SYS_SPACE);
/* Choose a rollback segment evenly distributed between 0 and
innodb_undo_logs-1 in a round-robin fashion, skipping those
@ -1012,7 +1012,7 @@ trx_assign_rseg_low()
do {
for (;;) {
rseg = trx_sys->rseg_array[slot];
rseg = trx_sys.rseg_array[slot];
#ifdef UNIV_DEBUG
/* Ensure that we are not revisiting the same
@ -1037,7 +1037,7 @@ trx_assign_rseg_low()
continue;
}
} else if (trx_rseg_t* next
= trx_sys->rseg_array[slot]) {
= trx_sys.rseg_array[slot]) {
if (next->space != TRX_SYS_SPACE
&& srv_undo_tablespaces > 0) {
/** If dedicated
@ -1082,17 +1082,17 @@ trx_t::assign_temp_rseg()
multiple transactions that start modifications concurrently
will write their undo log to the same rollback segment. */
static ulong rseg_slot;
trx_rseg_t* rseg = trx_sys->temp_rsegs[
trx_rseg_t* rseg = trx_sys.temp_rsegs[
rseg_slot++ & (TRX_SYS_N_RSEGS - 1)];
ut_ad(!rseg->is_persistent());
rsegs.m_noredo.rseg = rseg;
if (id == 0) {
mutex_enter(&trx_sys->mutex);
id = trx_sys->get_new_trx_id();
trx_sys->rw_trx_ids.push_back(id);
mutex_exit(&trx_sys->mutex);
trx_sys->rw_trx_hash.insert(this);
mutex_enter(&trx_sys.mutex);
id = trx_sys.get_new_trx_id();
trx_sys.rw_trx_ids.push_back(id);
mutex_exit(&trx_sys.mutex);
trx_sys.rw_trx_hash.insert(this);
}
ut_ad(!rseg->is_persistent());
@ -1152,12 +1152,12 @@ trx_start_low(
/* If this transaction came from trx_allocate_for_mysql(),
trx->in_mysql_trx_list would hold. In that case, the trx->state
change must be protected by the trx_sys->mutex, so that
change must be protected by the trx_sys.mutex, so that
lock_print_info_all_transactions() will have a consistent view. */
/* No other thread can access this trx object through rw_trx_hash, thus
we don't need trx_sys->mutex protection for that purpose. Still this
trx can be found through trx_sys->mysql_trx_list, which means state
we don't need trx_sys.mutex protection for that purpose. Still this
trx can be found through trx_sys.mysql_trx_list, which means state
change must be protected by e.g. trx->mutex.
For now we update it without mutex protection, because original code
@ -1178,24 +1178,24 @@ trx_start_low(
/* Temporary rseg is assigned only if the transaction
updates a temporary table */
trx_sys_mutex_enter();
mutex_enter(&trx_sys.mutex);
trx->id = trx_sys->get_new_trx_id();
trx->id = trx_sys.get_new_trx_id();
trx_sys->rw_trx_ids.push_back(trx->id);
trx_sys.rw_trx_ids.push_back(trx->id);
ut_ad(trx->rsegs.m_redo.rseg != 0
|| srv_read_only_mode
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
#ifdef UNIV_DEBUG
if (trx->id > trx_sys->rw_max_trx_id) {
trx_sys->rw_max_trx_id = trx->id;
if (trx->id > trx_sys.rw_max_trx_id) {
trx_sys.rw_max_trx_id = trx->id;
}
#endif /* UNIV_DEBUG */
trx_sys_mutex_exit();
trx_sys->rw_trx_hash.insert(trx);
mutex_exit(&trx_sys.mutex);
trx_sys.rw_trx_hash.insert(trx);
} else {
trx->id = 0;
@ -1208,16 +1208,16 @@ trx_start_low(
if (read_write) {
trx_sys_mutex_enter();
mutex_enter(&trx_sys.mutex);
ut_ad(!srv_read_only_mode);
trx->id = trx_sys->get_new_trx_id();
trx->id = trx_sys.get_new_trx_id();
trx_sys->rw_trx_ids.push_back(trx->id);
trx_sys.rw_trx_ids.push_back(trx->id);
trx_sys_mutex_exit();
trx_sys->rw_trx_hash.insert(trx);
mutex_exit(&trx_sys.mutex);
trx_sys.rw_trx_hash.insert(trx);
}
} else {
ut_ad(!read_write);
@ -1247,12 +1247,12 @@ trx_serialise(trx_t* trx, trx_rseg_t* rseg)
{
ut_ad(!rseg || rseg == trx->rsegs.m_redo.rseg);
trx_sys_mutex_enter();
mutex_enter(&trx_sys.mutex);
trx->no = trx_sys->get_new_trx_id();
trx->no = trx_sys.get_new_trx_id();
/* Track the minimum serialisation number. */
UT_LIST_ADD_LAST(trx_sys->serialisation_list, trx);
UT_LIST_ADD_LAST(trx_sys.serialisation_list, trx);
/* If the rollack segment is not empty then the
new trx_t::no can't be less than any trx_t::no
@ -1269,13 +1269,13 @@ trx_serialise(trx_t* trx, trx_rseg_t* rseg)
difference because this code path is only taken when the
rbs is empty. */
trx_sys_mutex_exit();
mutex_exit(&trx_sys.mutex);
purge_sys->purge_queue.push(elem);
mutex_exit(&purge_sys->pq_mutex);
} else {
trx_sys_mutex_exit();
mutex_exit(&trx_sys.mutex);
}
}
@ -1553,27 +1553,27 @@ trx_erase_lists(
if (trx->read_only || trx->rsegs.m_redo.rseg == NULL) {
trx_sys_mutex_enter();
mutex_enter(&trx_sys.mutex);
} else {
trx_sys_mutex_enter();
mutex_enter(&trx_sys.mutex);
if (trx->read_view != NULL) {
trx_sys->mvcc->view_close(trx->read_view, true);
trx_sys.mvcc->view_close(trx->read_view, true);
}
}
if (serialised) {
UT_LIST_REMOVE(trx_sys->serialisation_list, trx);
UT_LIST_REMOVE(trx_sys.serialisation_list, trx);
}
trx_ids_t::iterator it = std::lower_bound(
trx_sys->rw_trx_ids.begin(),
trx_sys->rw_trx_ids.end(),
trx_sys.rw_trx_ids.begin(),
trx_sys.rw_trx_ids.end(),
trx->id);
ut_ad(*it == trx->id);
trx_sys->rw_trx_ids.erase(it);
trx_sys_mutex_exit();
trx_sys->rw_trx_hash.erase(trx);
trx_sys.rw_trx_ids.erase(it);
mutex_exit(&trx_sys.mutex);
trx_sys.rw_trx_hash.erase(trx);
}
/****************************************************************//**
@ -1615,7 +1615,7 @@ trx_commit_in_memory(
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
if (trx->read_view != NULL) {
trx_sys->mvcc->view_close(trx->read_view, false);
trx_sys.mvcc->view_close(trx->read_view, false);
}
MONITOR_INC(MONITOR_TRX_NL_RO_COMMIT);
@ -1647,7 +1647,7 @@ trx_commit_in_memory(
if (trx->read_only || trx->rsegs.m_redo.rseg == NULL) {
MONITOR_INC(MONITOR_TRX_RO_COMMIT);
if (trx->read_view != NULL) {
trx_sys->mvcc->view_close(
trx_sys.mvcc->view_close(
trx->read_view, false);
}
} else {
@ -1911,7 +1911,7 @@ trx_assign_read_view(
return(NULL);
} else if (!MVCC::is_view_active(trx->read_view)) {
trx_sys->mvcc->view_open(trx->read_view, trx);
trx_sys.mvcc->view_open(trx->read_view, trx);
}
return(trx->read_view);
@ -1924,7 +1924,7 @@ trx_commit_or_rollback_prepare(
/*===========================*/
trx_t* trx) /*!< in/out: transaction */
{
/* We are reading trx->state without holding trx_sys->mutex
/* We are reading trx->state without holding trx_sys.mutex
here, because the commit or rollback should be invoked for a
running (or recovered prepared) transaction that is associated
with the current thread. */
@ -2150,7 +2150,7 @@ trx_print_low(
fprintf(f, "TRANSACTION " TRX_ID_FMT, trx_get_id_for_print(trx));
/* trx->state cannot change from or to NOT_STARTED while we
are holding the trx_sys->mutex. It may change from ACTIVE to
are holding the trx_sys.mutex. It may change from ACTIVE to
PREPARED or COMMITTED. */
switch (trx->state) {
case TRX_STATE_NOT_STARTED:
@ -2292,21 +2292,21 @@ trx_print(
#ifdef UNIV_DEBUG
/**********************************************************************//**
Asserts that a transaction has been started.
The caller must hold trx_sys->mutex.
The caller must hold trx_sys.mutex.
@return TRUE if started */
ibool
trx_assert_started(
/*===============*/
const trx_t* trx) /*!< in: transaction */
{
ut_ad(trx_sys_mutex_own());
ut_ad(mutex_own(&trx_sys.mutex));
/* Non-locking autocommits should not hold any locks and this
function is only called from the locking code. */
check_trx_state(trx);
/* trx->state can change from or to NOT_STARTED while we are holding
trx_sys->mutex for non-locking autocommit selects but not for other
trx_sys.mutex for non-locking autocommit selects but not for other
types of transactions. It may change from ACTIVE to PREPARED. Unless
we are holding lock_sys->mutex, it may also change to COMMITTED. */
@ -2441,9 +2441,9 @@ trx_prepare(
/*--------------------------------------*/
ut_a(trx->state == TRX_STATE_ACTIVE);
trx_sys_mutex_enter();
mutex_enter(&trx_sys.mutex);
trx->state = TRX_STATE_PREPARED;
trx_sys_mutex_exit();
mutex_exit(&trx_sys.mutex);
/*--------------------------------------*/
if (lsn) {
@ -2546,8 +2546,8 @@ int trx_recover_for_mysql(XID *xid_list, uint len)
ut_ad(len);
/* Fill xid_list with PREPARED transactions. */
trx_sys->rw_trx_hash.iterate_no_dups(reinterpret_cast<my_hash_walk_action>
(trx_recover_for_mysql_callback), &arg);
trx_sys.rw_trx_hash.iterate_no_dups(reinterpret_cast<my_hash_walk_action>
(trx_recover_for_mysql_callback), &arg);
if (arg.count)
ib::info() << arg.count
<< " transactions in prepared state after recovery";
@ -2598,8 +2598,8 @@ trx_t *trx_get_trx_by_xid(XID *xid)
trx_get_trx_by_xid_callback_arg arg= { xid, 0 };
if (xid)
trx_sys->rw_trx_hash.iterate(reinterpret_cast<my_hash_walk_action>
(trx_get_trx_by_xid_callback), &arg);
trx_sys.rw_trx_hash.iterate(reinterpret_cast<my_hash_walk_action>
(trx_get_trx_by_xid_callback), &arg);
return arg.trx;
}
@ -2757,7 +2757,7 @@ trx_set_rw_mode(
}
/* Function is promoting existing trx from ro mode to rw mode.
In this process it has acquired trx_sys->mutex as it plan to
In this process it has acquired trx_sys.mutex as it plan to
move trx from ro list to rw list. If in future, some other thread
looks at this trx object while it is being promoted then ensure
that both threads are synced by acquring trx->mutex to avoid decision
@ -2767,10 +2767,10 @@ trx_set_rw_mode(
ut_ad(trx->rsegs.m_redo.rseg != 0);
mutex_enter(&trx_sys->mutex);
trx->id = trx_sys->get_new_trx_id();
mutex_enter(&trx_sys.mutex);
trx->id = trx_sys.get_new_trx_id();
trx_sys->rw_trx_ids.push_back(trx->id);
trx_sys.rw_trx_ids.push_back(trx->id);
/* So that we can see our own changes. */
if (MVCC::is_view_active(trx->read_view)) {
@ -2778,12 +2778,12 @@ trx_set_rw_mode(
}
#ifdef UNIV_DEBUG
if (trx->id > trx_sys->rw_max_trx_id) {
trx_sys->rw_max_trx_id = trx->id;
if (trx->id > trx_sys.rw_max_trx_id) {
trx_sys.rw_max_trx_id = trx->id;
}
#endif /* UNIV_DEBUG */
mutex_exit(&trx_sys->mutex);
trx_sys->rw_trx_hash.insert(trx);
mutex_exit(&trx_sys.mutex);
trx_sys.rw_trx_hash.insert(trx);
}
/**

Loading…
Cancel
Save