Commit 0993d6b8 authored by Sergey Vojtovich's avatar Sergey Vojtovich

MDEV-15773 - trx_sys.mysql_trx_list -> trx_sys.trx_list

Replaced "list of transactions created for MySQL" with "list of all
transactions". This simplifies code and allows further removal of
trx_sys.m_views.
parent 061c767c
......@@ -2760,9 +2760,9 @@ buf_pool_resize()
lock_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.trx_list);
trx != NULL;
trx = UT_LIST_GET_NEXT(mysql_trx_list, trx)) {
trx = UT_LIST_GET_NEXT(trx_list, trx)) {
if (trx->state != TRX_STATE_NOT_STARTED
&& trx->mysql_thd != NULL
&& ut_difftime(withdraw_started,
......
......@@ -2741,7 +2741,7 @@ innobase_trx_allocate(
DBUG_ASSERT(thd != NULL);
DBUG_ASSERT(EQ_CURRENT_THD(thd));
trx = trx_allocate_for_mysql();
trx = trx_create();
trx->mysql_thd = thd;
......
......@@ -808,20 +808,11 @@ class trx_sys_t
bool m_initialised;
public:
MY_ALIGNED(CACHE_LINE_SIZE) mutable
TrxSysMutex mutex; /*!< mutex protecting most fields in
this structure except when noted
otherwise */
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
can contain system transactions and
recovered transactions that will not
be in the mysql_trx_list.
mysql_trx_list may additionally contain
transactions that have not yet been
started in InnoDB. */
/** Mutex protecting trx_list. */
MY_ALIGNED(CACHE_LINE_SIZE) mutable TrxSysMutex mutex;
/** List of all transactions. */
MY_ALIGNED(CACHE_LINE_SIZE) trx_ut_list_t trx_list;
MY_ALIGNED(CACHE_LINE_SIZE)
/** Temporary rollback segments */
......
......@@ -82,12 +82,6 @@ const dict_index_t*
trx_get_error_info(
/*===============*/
const trx_t* trx); /*!< in: trx object */
/********************************************************************//**
Creates a transaction object for MySQL.
@return own: transaction object */
trx_t*
trx_allocate_for_mysql(void);
/*========================*/
/** @return a trx_t instance from trx_pools. */
trx_t *trx_create();
......@@ -106,11 +100,6 @@ trx_free_at_shutdown(trx_t *trx);
void
trx_free_for_mysql(trx_t* trx);
/** Disconnect a transaction from MySQL.
@param[in,out] trx transaction */
void
trx_disconnect_plain(trx_t* trx);
/** Disconnect a prepared transaction from MySQL.
@param[in,out] trx transaction */
void
......@@ -514,7 +503,7 @@ transaction pool.
/*******************************************************************//**
Assert that an autocommit non-locking select cannot be in the
rw_trx_hash and that it is a read-only transaction.
The tranasction must be in the mysql_trx_list. */
The transaction must have mysql_thd assigned. */
# define assert_trx_nonlocking_or_in_list(t) \
do { \
if (trx_is_autocommit_non_locking(t)) { \
......@@ -532,7 +521,7 @@ The tranasction must be in the mysql_trx_list. */
/*******************************************************************//**
Assert that an autocommit non-locking slect cannot be in the
rw_trx_hash and that it is a read-only transaction.
The tranasction must be in the mysql_trx_list. */
The transaction must have mysql_thd assigned. */
# define assert_trx_nonlocking_or_in_list(trx) ((void)0)
#endif /* UNIV_DEBUG */
......@@ -733,9 +722,8 @@ 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.trx_list, some of its fields
must not be modified without holding trx->mutex.
* The locking code (in particular, lock_deadlock_recursive() and
lock_rec_convert_impl_to_expl()) will access transactions associated
......@@ -854,8 +842,8 @@ struct trx_t {
do we remove it from the read-only list and put it on the read-write
list. During this switch we assign it a rollback segment.
When a transaction is NOT_STARTED, it can be in mysql_trx_list if
it is a user transaction. It cannot be in rw_trx_hash.
When a transaction is NOT_STARTED, it can be in trx_list. 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.
......@@ -973,9 +961,8 @@ struct trx_t {
statement uses, except those
in consistent read */
/*------------------------------*/
UT_LIST_NODE_T(trx_t)
mysql_trx_list; /*!< list of transactions created for
MySQL; protected by trx_sys.mutex */
UT_LIST_NODE_T(trx_t) trx_list; /*!< list of all transactions;
protected by trx_sys.mutex */
/*------------------------------*/
dberr_t error_state; /*!< 0 if no error, otherwise error
number; NOTE That ONLY the thread
......
......@@ -4666,7 +4666,7 @@ lock_print_info_summary(
return(TRUE);
}
/** Functor to print not-started transaction from the mysql_trx_list. */
/** Functor to print not-started transaction from the trx_list. */
struct PrintNotStarted {
......@@ -4674,12 +4674,12 @@ struct PrintNotStarted {
void operator()(const trx_t* trx)
{
ut_ad(trx->mysql_thd);
ut_ad(mutex_own(&trx_sys.mutex));
/* See state transitions and locking rules in trx0trx.h */
if (trx_state_eq(trx, TRX_STATE_NOT_STARTED)) {
if (trx->mysql_thd
&& trx_state_eq(trx, TRX_STATE_NOT_STARTED)) {
fputs("---", m_file);
trx_print_latched(m_file, trx, 600);
......@@ -4806,7 +4806,7 @@ lock_print_info_all_transactions(
PrintNotStarted print_not_started(file);
mutex_enter(&trx_sys.mutex);
ut_list_map(trx_sys.mysql_trx_list, print_not_started);
ut_list_map(trx_sys.trx_list, print_not_started);
mutex_exit(&trx_sys.mutex);
trx_sys.rw_trx_hash.iterate_no_dups(
......
......@@ -3728,7 +3728,7 @@ row_import_for_mysql(
trx_start_if_not_started(prebuilt->trx, true);
trx = trx_allocate_for_mysql();
trx = trx_create();
/* So that the table is not DROPped during recovery. */
trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
......
......@@ -2872,8 +2872,8 @@ innodb_shutdown()
if (log_sys) {
log_shutdown();
}
trx_sys.close();
purge_sys.close();
trx_sys.close();
if (buf_dblwr) {
buf_dblwr_free();
}
......
......@@ -56,6 +56,8 @@ Created July 17, 2007 Vasil Dimov
#include "trx0sys.h"
#include "trx0trx.h"
#include "ut0mem.h"
#include "que0que.h"
#include "trx0purge.h"
/** Initial number of rows in the table cache */
#define TABLE_CACHE_INITIAL_ROWSNUM 1024
......@@ -1275,17 +1277,6 @@ static void fetch_data_into_cache_low(trx_i_s_cache_t *cache, const trx_t *trx)
}
static my_bool fetch_data_into_cache_callback(
rw_trx_hash_element_t *element, trx_i_s_cache_t *cache)
{
mutex_enter(&element->mutex);
if (element->trx)
fetch_data_into_cache_low(cache, element->trx);
mutex_exit(&element->mutex);
return cache->is_truncated;
}
/**
Fetches the data needed to fill the 3 INFORMATION SCHEMA tables into the
table cache buffer. Cache must be locked for write.
......@@ -1296,24 +1287,13 @@ static void fetch_data_into_cache(trx_i_s_cache_t *cache)
ut_ad(lock_mutex_own());
trx_i_s_cache_clear(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);
/* Capture the state of the read-only active transactions */
/* Capture the state of transactions */
mutex_enter(&trx_sys.mutex);
for (const trx_t *trx= UT_LIST_GET_FIRST(trx_sys.mysql_trx_list);
for (const trx_t *trx= UT_LIST_GET_FIRST(trx_sys.trx_list);
trx != NULL;
trx= UT_LIST_GET_NEXT(mysql_trx_list, trx))
trx= UT_LIST_GET_NEXT(trx_list, trx))
{
/*
Skip transactions that have trx->id > 0: they were added in previous
iteration. Although we may miss concurrently started transactions.
*/
if (trx_is_started(trx) && trx->id == 0)
if (trx_is_started(trx) && trx != purge_sys.query->trx)
{
fetch_data_into_cache_low(cache, trx);
if (cache->is_truncated)
......
......@@ -759,14 +759,14 @@ trx_roll_must_shutdown()
static my_bool trx_rollback_recovered_callback(rw_trx_hash_element_t *element,
trx_ut_list_t *trx_list)
std::vector<trx_t*> *trx_list)
{
mutex_enter(&element->mutex);
if (trx_t *trx= element->trx)
{
mutex_enter(&trx->mutex);
if (trx->is_recovered && trx_state_eq(trx, TRX_STATE_ACTIVE))
UT_LIST_ADD_FIRST(*trx_list, trx);
trx_list->push_back(trx);
mutex_exit(&trx->mutex);
}
mutex_exit(&element->mutex);
......@@ -791,10 +791,9 @@ static my_bool trx_rollback_recovered_callback(rw_trx_hash_element_t *element,
void trx_rollback_recovered(bool all)
{
trx_ut_list_t trx_list;
std::vector<trx_t*> trx_list;
ut_a(srv_force_recovery < SRV_FORCE_NO_TRX_UNDO);
UT_LIST_INIT(trx_list, &trx_t::mysql_trx_list);
/*
Collect list of recovered ACTIVE transaction ids first. Once collected, no
......@@ -805,9 +804,10 @@ void trx_rollback_recovered(bool all)
(trx_rollback_recovered_callback),
&trx_list);
while (trx_t *trx= UT_LIST_GET_FIRST(trx_list))
while (!trx_list.empty())
{
UT_LIST_REMOVE(trx_list, trx);
trx_t *trx= trx_list.back();
trx_list.pop_back();
#ifdef UNIV_DEBUG
ut_ad(trx);
......
......@@ -217,7 +217,7 @@ trx_sys_t::create()
ut_ad(!is_initialised());
m_initialised = true;
mutex_create(LATCH_ID_TRX_SYS, &mutex);
UT_LIST_INIT(mysql_trx_list, &trx_t::mysql_trx_list);
UT_LIST_INIT(trx_list, &trx_t::trx_list);
UT_LIST_INIT(m_views, &ReadView::m_view_list);
my_atomic_store32(&rseg_history_len, 0);
......@@ -345,47 +345,26 @@ trx_sys_t::close()
}
}
ut_a(UT_LIST_GET_LEN(mysql_trx_list) == 0);
ut_a(UT_LIST_GET_LEN(trx_list) == 0);
ut_ad(UT_LIST_GET_LEN(m_views) == 0);
mutex_free(&mutex);
m_initialised = false;
}
static my_bool active_count_callback(rw_trx_hash_element_t *element,
uint32_t *count)
{
mutex_enter(&element->mutex);
if (trx_t *trx= element->trx)
{
mutex_enter(&trx->mutex);
if (trx_state_eq(trx, TRX_STATE_ACTIVE))
++*count;
mutex_exit(&trx->mutex);
}
mutex_exit(&element->mutex);
return 0;
}
/** @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(
reinterpret_cast<my_hash_walk_action>
(active_count_callback), &total_trx);
mutex_enter(&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++;
}
}
mutex_exit(&mutex);
uint32_t total_trx= 0;
return(total_trx);
mutex_enter(&mutex);
for (trx_t* trx= UT_LIST_GET_FIRST(trx_sys.trx_list);
trx != NULL;
trx= UT_LIST_GET_NEXT(trx_list, trx))
{
if (trx->state == TRX_STATE_COMMITTED_IN_MEMORY ||
(trx->state == TRX_STATE_ACTIVE && trx->id))
total_trx++;
}
mutex_exit(&mutex);
return total_trx;
}
......@@ -423,6 +423,10 @@ trx_t *trx_create()
trx->wsrep_event = NULL;
#endif /* WITH_WSREP */
mutex_enter(&trx_sys.mutex);
UT_LIST_ADD_FIRST(trx_sys.trx_list, trx);
mutex_exit(&trx_sys.mutex);
return(trx);
}
......@@ -433,6 +437,10 @@ static
void
trx_free(trx_t*& trx)
{
mutex_enter(&trx_sys.mutex);
UT_LIST_REMOVE(trx_sys.trx_list, trx);
mutex_exit(&trx_sys.mutex);
assert_trx_is_free(trx);
trx_sys.rw_trx_hash.put_pins(trx);
......@@ -461,24 +469,6 @@ trx_free(trx_t*& trx)
trx = NULL;
}
/********************************************************************//**
Creates a transaction object for MySQL.
@return own: transaction object */
trx_t*
trx_allocate_for_mysql(void)
/*========================*/
{
trx_t* trx;
trx = trx_create();
mutex_enter(&trx_sys.mutex);
UT_LIST_ADD_FIRST(trx_sys.mysql_trx_list, trx);
mutex_exit(&trx_sys.mutex);
return(trx);
}
/** Check state of transaction before freeing it.
@param trx trx object to validate */
static
......@@ -567,62 +557,30 @@ trx_free_at_shutdown(trx_t *trx)
trx_free(trx);
}
/** Disconnect a transaction from MySQL and optionally mark it as if
it's been recovered. For the marking the transaction must be in prepared state.
The recovery-marked transaction is going to survive "alone" so its association
with the mysql handle is destroyed now rather than when it will be
finally freed.
@param[in,out] trx transaction
@param[in] prepared boolean value to specify whether trx is
for recovery or not. */
inline
void
trx_disconnect_from_mysql(
trx_t* trx,
bool prepared)
{
ut_ad(trx->mysql_thd);
trx->read_view.close();
mutex_enter(&trx_sys.mutex);
UT_LIST_REMOVE(trx_sys.mysql_trx_list, trx);
if (prepared) {
ut_ad(trx_state_eq(trx, TRX_STATE_PREPARED));
trx->is_recovered = true;
trx->mysql_thd = NULL;
/* todo/fixme: suggest to do it at innodb prepare */
trx->will_lock = 0;
}
mutex_exit(&trx_sys.mutex);
}
/** Disconnect a transaction from MySQL.
@param[in,out] trx transaction */
inline
void
trx_disconnect_plain(trx_t* trx)
{
trx_disconnect_from_mysql(trx, false);
}
/** Disconnect a prepared transaction from MySQL.
@param[in,out] trx transaction */
void
trx_disconnect_prepared(trx_t* trx)
/**
Disconnect a prepared transaction from MySQL
@param[in,out] trx transaction
*/
void trx_disconnect_prepared(trx_t *trx)
{
trx_disconnect_from_mysql(trx, true);
ut_ad(trx_state_eq(trx, TRX_STATE_PREPARED));
ut_ad(trx->mysql_thd);
trx->read_view.close();
trx->is_recovered= true;
trx->mysql_thd= NULL;
/* todo/fixme: suggest to do it at innodb prepare */
trx->will_lock= 0;
}
/** Free a transaction object for MySQL.
@param[in,out] trx transaction */
void
trx_free_for_mysql(trx_t* trx)
/**
Free a transaction object for MySQL
@param[in,out] trx transaction
*/
void trx_free_for_mysql(trx_t *trx)
{
trx_disconnect_plain(trx);
trx_free_for_background(trx);
ut_ad(trx->mysql_thd);
trx_free_for_background(trx);
}
/****************************************************************//**
......@@ -1054,7 +1012,7 @@ trx_start_low(
/* 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
trx can be found through trx_sys.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
......@@ -1397,7 +1355,7 @@ trx_commit_in_memory(
there is an inherent race here around state transition during
printouts. We ignore this race for the sake of efficiency.
However, the trx_sys_t::mutex will protect the trx_t instance
and it cannot be removed from the mysql_trx_list and freed
and it cannot be removed from the trx_list and freed
without first acquiring the trx_sys_t::mutex. */
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
......@@ -1527,9 +1485,6 @@ trx_commit_in_memory(
DBUG_LOG("trx", "Commit in memory: " << trx);
trx->state = TRX_STATE_NOT_STARTED;
/* trx->mysql_thd != 0 would hold between
trx_allocate_for_mysql() and trx_free_for_mysql(). It does not
hold for recovered transactions or system transactions. */
assert_trx_is_free(trx);
trx_init(trx);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment