Skip to content

Commit

Permalink
MDEV-15773 - Simplified away trx_sys_t::m_views
Browse files Browse the repository at this point in the history
Use trx_sys_t::trx_list instead.
  • Loading branch information
Sergey Vojtovich committed Apr 4, 2018
1 parent 3d5f7ad commit e6a9ce2
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 120 deletions.
64 changes: 19 additions & 45 deletions storage/innobase/include/read0types.h
Expand Up @@ -33,17 +33,14 @@ Created 2/16/1997 Heikki Tuuri
#include "trx0types.h"


/** View is not in MVCC and not visible to purge thread. */
/** View is not visible to purge thread. */
#define READ_VIEW_STATE_CLOSED 0

/** View is in MVCC, but not visible to purge thread. */
#define READ_VIEW_STATE_REGISTERED 1
/** View is being opened, purge thread must wait for state change. */
#define READ_VIEW_STATE_SNAPSHOT 1

/** View is in MVCC, purge thread must wait for READ_VIEW_STATE_OPEN. */
#define READ_VIEW_STATE_SNAPSHOT 2

/** View is in MVCC and is visible to purge thread. */
#define READ_VIEW_STATE_OPEN 3
/** View is visible to purge thread. */
#define READ_VIEW_STATE_OPEN 2


/**
Expand All @@ -56,34 +53,25 @@ class ReadView
View state.
It is not defined as enum as it has to be updated using atomic operations.
Possible values are READ_VIEW_STATE_CLOSED, READ_VIEW_STATE_REGISTERED,
READ_VIEW_STATE_SNAPSHOT and READ_VIEW_STATE_OPEN.
Possible values are READ_VIEW_STATE_CLOSED, READ_VIEW_STATE_SNAPSHOT and
READ_VIEW_STATE_OPEN.
Possible state transfers...
Opening view for the first time:
READ_VIEW_STATE_CLOSED -> READ_VIEW_STATE_SNAPSHOT (non-atomic)
Complete first time open or reopen:
READ_VIEW_STATE_SNAPSHOT -> READ_VIEW_STATE_OPEN (atomic)
Close view but keep it in list:
READ_VIEW_STATE_OPEN -> READ_VIEW_STATE_REGISTERED (atomic)
Start view open:
READ_VIEW_STATE_CLOSED -> READ_VIEW_STATE_SNAPSHOT
Close view and remove it from list:
READ_VIEW_STATE_OPEN -> READ_VIEW_STATE_CLOSED (non-atomic)
Complete view open:
READ_VIEW_STATE_SNAPSHOT -> READ_VIEW_STATE_OPEN
Reusing view:
READ_VIEW_STATE_REGISTERED -> READ_VIEW_STATE_SNAPSHOT (atomic)
Removing closed view from list:
READ_VIEW_STATE_REGISTERED -> READ_VIEW_STATE_CLOSED (non-atomic)
Close view:
READ_VIEW_STATE_OPEN -> READ_VIEW_STATE_CLOSED
*/
int32_t m_state;


public:
ReadView(): m_state(READ_VIEW_STATE_CLOSED) {}
ReadView(): m_state(READ_VIEW_STATE_CLOSED), m_low_limit_id(0) {}


/**
Expand Down Expand Up @@ -136,7 +124,7 @@ class ReadView
Opens a read view where exactly the transactions serialized before this
point in time are seen in the view.
View becomes visible to purge thread via trx_sys.m_views.
View becomes visible to purge thread.
@param[in,out] trx transaction
*/
Expand All @@ -146,23 +134,14 @@ class ReadView
/**
Closes the view.
View becomes not visible to purge thread via trx_sys.m_views.
View becomes not visible to purge thread.
*/
void close();


/**
Marks view unused.
View is still in trx_sys.m_views list, but is not visible to purge threads.
*/
void unuse()
void close()
{
ut_ad(m_state == READ_VIEW_STATE_CLOSED ||
m_state == READ_VIEW_STATE_REGISTERED ||
m_state == READ_VIEW_STATE_OPEN);
if (m_state == READ_VIEW_STATE_OPEN)
my_atomic_store32_explicit(&m_state, READ_VIEW_STATE_REGISTERED,
my_atomic_store32_explicit(&m_state, READ_VIEW_STATE_CLOSED,
MY_MEMORY_ORDER_RELAXED);
}

Expand All @@ -183,8 +162,7 @@ class ReadView
bool is_open() const
{
ut_ad(m_state == READ_VIEW_STATE_OPEN ||
m_state == READ_VIEW_STATE_CLOSED ||
m_state == READ_VIEW_STATE_REGISTERED);
m_state == READ_VIEW_STATE_CLOSED);
return m_state == READ_VIEW_STATE_OPEN;
}

Expand Down Expand Up @@ -302,10 +280,6 @@ class ReadView
whose transaction number is strictly smaller (<) than this value:
they can be removed in purge if not needed by other views */
trx_id_t m_low_limit_no;

byte pad1[CACHE_LINE_SIZE];
public:
UT_LIST_NODE_T(ReadView) m_view_list;
};

#endif
25 changes: 11 additions & 14 deletions storage/innobase/include/trx0sys.h
Expand Up @@ -802,9 +802,6 @@ class trx_sys_t
*/
MY_ALIGNED(CACHE_LINE_SIZE) int32 rseg_history_len;

/** Active views. */
MY_ALIGNED(CACHE_LINE_SIZE) UT_LIST_BASE_NODE_T(ReadView) m_views;

bool m_initialised;

public:
Expand Down Expand Up @@ -1051,27 +1048,27 @@ class trx_sys_t


/**
Registers view in MVCC.
Registers transaction in trx_sys.
@param view view owned by the caller
@param trx transaction
*/
void register_view(ReadView *view)
void register_trx(trx_t *trx)
{
mutex_enter(&mutex);
UT_LIST_ADD_FIRST(m_views, view);
UT_LIST_ADD_FIRST(trx_list, trx);
mutex_exit(&mutex);
}


/**
Deregisters view in MVCC.
Deregisters transaction in trx_sys.
@param view view owned by the caller
@param trx transaction
*/
void deregister_view(ReadView *view)
void deregister_trx(trx_t *trx)
{
mutex_enter(&mutex);
UT_LIST_REMOVE(m_views, view);
UT_LIST_REMOVE(trx_list, trx);
mutex_exit(&mutex);
}

Expand All @@ -1092,10 +1089,10 @@ class trx_sys_t
size_t count= 0;

mutex_enter(&mutex);
for (const ReadView* view= UT_LIST_GET_FIRST(m_views); view;
view= UT_LIST_GET_NEXT(m_view_list, view))
for (const trx_t *trx= UT_LIST_GET_FIRST(trx_list); trx;
trx= UT_LIST_GET_NEXT(trx_list, trx))
{
if (view->get_state() == READ_VIEW_STATE_OPEN)
if (trx->read_view.get_state() == READ_VIEW_STATE_OPEN)
++count;
}
mutex_exit(&mutex);
Expand Down
57 changes: 8 additions & 49 deletions storage/innobase/read/read0read.cc
Expand Up @@ -193,7 +193,7 @@ inline void ReadView::snapshot(trx_t *trx)
Opens a read view where exactly the transactions serialized before this
point in time are seen in the view.
View becomes visible to purge thread via trx_sys.m_views.
View becomes visible to purge thread.
@param[in,out] trx transaction
*/
Expand All @@ -205,8 +205,9 @@ void ReadView::open(trx_t *trx)
case READ_VIEW_STATE_OPEN:
ut_ad(!srv_read_only_mode);
return;
case READ_VIEW_STATE_REGISTERED:
ut_ad(!srv_read_only_mode);
case READ_VIEW_STATE_CLOSED:
if (srv_read_only_mode)
return;
/*
Reuse closed view if there were no read-write transactions since (and at)
its creation time.
Expand All @@ -224,18 +225,6 @@ void ReadView::open(trx_t *trx)
What bad things can happen because we allow this race?
First, purge thread may be affected by this race condition only if this
view is the oldest open view. In other words this view is either last in
m_views list or there're no open views beyond.
In this case purge may not catch this view and clone some younger view
instead. It might be kind of alright, because there were no read-write
transactions and there should be nothing to purge. Besides younger view
must have exactly the same values.
Second, scary things start when there's a read-write transaction starting
concurrently.
Speculative execution may reorder state change before get_max_trx_id().
In this case purge thread has short gap to clone outdated view. Which is
probably not that bad: it just won't be able to purge things that it was
Expand Down Expand Up @@ -268,12 +257,6 @@ void ReadView::open(trx_t *trx)
my_atomic_store32_explicit(&m_state, READ_VIEW_STATE_SNAPSHOT,
MY_MEMORY_ORDER_RELAXED);
break;
case READ_VIEW_STATE_CLOSED:
if (srv_read_only_mode)
return;
m_state= READ_VIEW_STATE_SNAPSHOT;
trx_sys.register_view(this);
break;
default:
ut_ad(0);
}
Expand All @@ -286,52 +269,28 @@ void ReadView::open(trx_t *trx)
}


/**
Closes the view.
The view will become invisible to purge (deregistered from trx_sys).
*/
void ReadView::close()
{
ut_ad(m_state == READ_VIEW_STATE_OPEN ||
m_state == READ_VIEW_STATE_REGISTERED ||
m_state == READ_VIEW_STATE_CLOSED);
if (m_state != READ_VIEW_STATE_CLOSED)
{
trx_sys.deregister_view(this);
m_state= READ_VIEW_STATE_CLOSED;
}
}


/**
Clones the oldest view and stores it in view.
No need to call ReadView::close(). The caller owns the view that is passed
in. This function is called by purge thread to determine whether it should
purge the delete marked record or not.
Since foreign views are accessed under the mutex protection, the only
possible state transfers are
READ_VIEW_STATE_SNAPSHOT -> READ_VIEW_STATE_OPEN
READ_VIEW_STATE_OPEN -> READ_VIEW_STATE_REGISTERED
All other state transfers are eliminated by the mutex.
*/
void trx_sys_t::clone_oldest_view()
{
purge_sys.view.snapshot(0);
mutex_enter(&mutex);
/* Find oldest view. */
for (const ReadView *v= UT_LIST_GET_FIRST(m_views); v;
v= UT_LIST_GET_NEXT(m_view_list, v))
for (const trx_t *trx= UT_LIST_GET_FIRST(trx_list); trx;
trx= UT_LIST_GET_NEXT(trx_list, trx))
{
int32_t state;

while ((state= v->get_state()) == READ_VIEW_STATE_SNAPSHOT)
while ((state= trx->read_view.get_state()) == READ_VIEW_STATE_SNAPSHOT)
ut_delay(1);

if (state == READ_VIEW_STATE_OPEN)
purge_sys.view.copy(*v);
purge_sys.view.copy(trx->read_view);
}
mutex_exit(&mutex);
}
2 changes: 0 additions & 2 deletions storage/innobase/trx/trx0sys.cc
Expand Up @@ -218,7 +218,6 @@ trx_sys_t::create()
m_initialised = true;
mutex_create(LATCH_ID_TRX_SYS, &mutex);
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);

rw_trx_hash.init();
Expand Down Expand Up @@ -346,7 +345,6 @@ trx_sys_t::close()
}

ut_a(UT_LIST_GET_LEN(trx_list) == 0);
ut_ad(UT_LIST_GET_LEN(m_views) == 0);
mutex_free(&mutex);
m_initialised = false;
}
Expand Down
13 changes: 3 additions & 10 deletions storage/innobase/trx/trx0trx.cc
Expand Up @@ -423,9 +423,7 @@ 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);
trx_sys.register_trx(trx);

return(trx);
}
Expand Down Expand Up @@ -472,9 +470,7 @@ void trx_free(trx_t*& trx)
trx->dict_operation = TRX_DICT_OP_NONE;
assert_trx_is_inactive(trx);

mutex_enter(&trx_sys.mutex);
UT_LIST_REMOVE(trx_sys.trx_list, trx);
mutex_exit(&trx_sys.mutex);
trx_sys.deregister_trx(trx);

assert_trx_is_free(trx);

Expand All @@ -492,9 +488,6 @@ void trx_free(trx_t*& trx)

trx->mod_tables.clear();

ut_ad(!trx->read_view.is_open());
trx->read_view.close();

/* trx locking state should have been reset before returning trx
to pool */
ut_ad(trx->will_lock == 0);
Expand Down Expand Up @@ -1308,7 +1301,7 @@ trx_commit_in_memory(
the transaction did not modify anything */
{
trx->must_flush_log_later = false;
trx->read_view.unuse();
trx->read_view.close();

if (trx_is_autocommit_non_locking(trx)) {
ut_ad(trx->id == 0);
Expand Down

0 comments on commit e6a9ce2

Please sign in to comment.