Skip to content

Commit 4dc30f3

Browse files
committed
MDEV-15019 - InnoDB: store ReadView on trx
This will allow us to reduce critical section protected by trx_sys.mutex: - no need to maintain global m_free list - eliminate if (trx->read_view == NULL) condition. On x86_64 sizeof(Readview) is 144 mostly due to padding, sizeof(trx_t) with ReadView is 1200. Also don't close ReadView for read-write transactions, just mark it closed similarly to read-only. Clean-up: removed n_prepared_recovered_trx and n_prepared_trx, which accidentally re-appeared after some rebase.
1 parent ec32c05 commit 4dc30f3

File tree

13 files changed

+196
-321
lines changed

13 files changed

+196
-321
lines changed

storage/innobase/handler/ha_innodb.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3503,7 +3503,7 @@ ha_innobase::init_table_handle_for_HANDLER(void)
35033503

35043504
/* Assign a read view if the transaction does not have it yet */
35053505

3506-
trx_assign_read_view(m_prebuilt->trx);
3506+
trx_sys.mvcc.view_open(m_prebuilt->trx);
35073507

35083508
innobase_register_trx(ht, m_user_thd, m_prebuilt->trx);
35093509

@@ -4394,7 +4394,7 @@ innobase_start_trx_and_assign_read_view(
43944394
thd_get_trx_isolation(thd));
43954395

43964396
if (trx->isolation_level == TRX_ISO_REPEATABLE_READ) {
4397-
trx_assign_read_view(trx);
4397+
trx_sys.mvcc.view_open(trx);
43984398
} else {
43994399
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
44004400
HA_ERR_UNSUPPORTED,
@@ -16220,7 +16220,7 @@ ha_innobase::external_lock(
1622016220
}
1622116221

1622216222
} else if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
16223-
&& MVCC::is_view_active(trx->read_view)) {
16223+
&& trx->read_view.is_open()) {
1622416224
mutex_enter(&trx_sys.mutex);
1622516225
trx_sys.mvcc.view_close(trx->read_view);
1622616226
mutex_exit(&trx_sys.mutex);
@@ -16885,7 +16885,7 @@ ha_innobase::store_lock(
1688516885
(enum_tx_isolation) thd_tx_isolation(thd));
1688616886

1688716887
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
16888-
&& MVCC::is_view_active(trx->read_view)) {
16888+
&& trx->read_view.is_open()) {
1688916889

1689016890
/* At low transaction isolation levels we let
1689116891
each consistent read set its own snapshot */

storage/innobase/handler/handler0alter.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5562,7 +5562,7 @@ prepare_inplace_alter_table_dict(
55625562
if (ctx->online && ctx->num_to_add_index) {
55635563
/* Assign a consistent read view for
55645564
row_merge_read_clustered_index(). */
5565-
trx_assign_read_view(ctx->prebuilt->trx);
5565+
trx_sys.mvcc.view_open(ctx->prebuilt->trx);
55665566
}
55675567

55685568
if (fts_index) {

storage/innobase/include/read0read.h

Lines changed: 44 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -31,60 +31,51 @@ Created 2/16/1997 Heikki Tuuri
3131
#include "read0types.h"
3232

3333
/** The MVCC read view manager */
34-
class MVCC {
34+
class MVCC
35+
{
36+
/** Active views. */
37+
UT_LIST_BASE_NODE_T(ReadView) m_views;
38+
39+
40+
/** Validates a read view list. */
41+
bool validate() const;
3542
public:
36-
/** Constructor
37-
@param size Number of views to pre-allocate */
38-
void create(ulint size);
39-
40-
/** Destructor.
41-
Free all the views in the m_free list */
42-
void close();
43-
44-
/**
45-
Allocate and create a view.
46-
@param view view owned by this class created for the
47-
caller. Must be freed by calling close()
48-
@param trx transaction creating the view */
49-
void view_open(ReadView*& view, trx_t* trx);
50-
51-
/**
52-
Close a view created by the above function.
53-
@param view view allocated by trx_open. */
54-
void view_close(ReadView*& view);
55-
56-
/** Clones the oldest view and stores it in view. No need to
57-
call view_close(). The caller owns the view that is passed in.
58-
It will also move the closed views from the m_views list to the
59-
m_free list. This function is called by Purge to create it view.
60-
@param view Preallocated view, owned by the caller */
61-
void clone_oldest_view(ReadView* view);
62-
63-
/**
64-
@return the number of active views */
65-
ulint size() const;
66-
67-
/**
68-
@return true if the view is active and valid */
69-
static bool is_view_active(ReadView* view)
70-
{
71-
return view && !view->is_closed();
72-
}
73-
74-
private:
75-
76-
/**
77-
Validates a read view list. */
78-
bool validate() const;
79-
80-
typedef UT_LIST_BASE_NODE_T(ReadView) view_list_t;
81-
82-
/** Free views ready for reuse. */
83-
view_list_tm_free;
84-
85-
/** Active and closed views, the closed views will have the
86-
creator trx id set to TRX_ID_MAX */
87-
view_list_tm_views;
43+
MVCC() { UT_LIST_INIT(m_views, &ReadView::m_view_list); }
44+
~MVCC() { ut_ad(UT_LIST_GET_LEN(m_views) == 0); }
45+
46+
47+
/**
48+
Allocate and create a view.
49+
@param trx transaction creating the view
50+
*/
51+
void view_open(trx_t *trx);
52+
53+
54+
/**
55+
Close a view created by the above function.
56+
@param view view allocated by view_open.
57+
*/
58+
void view_close(ReadView &view)
59+
{
60+
view.close();
61+
view.set_registered(false);
62+
UT_LIST_REMOVE(m_views, &view);
63+
ut_ad(validate());
64+
}
65+
66+
67+
/**
68+
Clones the oldest view and stores it in view. No need to
69+
call view_close(). The caller owns the view that is passed in.
70+
This function is called by Purge to create it view.
71+
72+
@param view Preallocated view, owned by the caller
73+
*/
74+
void clone_oldest_view(ReadView *view);
75+
76+
77+
/** @return the number of active views */
78+
size_t size() const;
8879
};
8980

9081
#endif /* read0read_h */

storage/innobase/include/read0types.h

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -198,19 +198,13 @@ class ReadView {
198198
{
199199
ut_ad(m_creator_trx_id != TRX_ID_MAX);
200200
m_creator_trx_id = TRX_ID_MAX;
201+
set_open(false);
201202
}
202203

203-
/**
204-
@return true if the view is closed */
205-
bool is_closed() const
206-
{
207-
return(m_closed);
208-
}
209-
210-
void set_closed(bool closed)
211-
{
212-
m_closed= closed;
213-
}
204+
bool is_open() const { return(m_open); }
205+
void set_open(bool open) { m_open= open; }
206+
bool is_registered() const { return(m_registered); }
207+
void set_registered(bool registered) { m_registered= registered; }
214208

215209
/**
216210
Write the limits to the file.
@@ -325,14 +319,15 @@ class ReadView {
325319
they can be removed in purge if not needed by other views */
326320
trx_id_tm_low_limit_no;
327321

328-
/** AC-NL-RO transaction view that has been "closed". */
329-
boolm_closed;
322+
/** true if view is open. */
323+
boolm_open;
330324

331-
typedef UT_LIST_NODE_T(ReadView) node_t;
325+
/** true if transaction is in MVCC::m_views. Only thread that owns
326+
this view may access it. */
327+
boolm_registered;
332328

333-
/** List of read views in trx_sys */
334-
byte pad1[64 - sizeof(node_t)];
335-
node_tm_view_list;
329+
byte pad1[CACHE_LINE_SIZE];
330+
UT_LIST_NODE_T(ReadView) m_view_list;
336331
};
337332

338333
#endif

storage/innobase/include/trx0sys.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -883,17 +883,6 @@ struct trx_sys_t {
883883

884884
MY_ALIGNED(CACHE_LINE_SIZE) rw_trx_hash_t rw_trx_hash;
885885

886-
ulint n_prepared_trx;/*!< Number of transactions currently
887-
in the XA PREPARED state */
888-
889-
ulint n_prepared_recovered_trx; /*!< Number of transactions
890-
currently in XA PREPARED state that are
891-
also recovered. Such transactions cannot
892-
be added during runtime. They can only
893-
occur after recovery if mysqld crashed
894-
while there were XA PREPARED
895-
transactions. We disable query cache
896-
if such transactions exist. */
897886

898887
/**
899888
Constructor.

storage/innobase/include/trx0trx.h

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,11 @@ Created 3/26/1996 Heikki Tuuri
4545
#include "ut0vec.h"
4646
#include "fts0fts.h"
4747
#include "srv0srv.h"
48+
#include "read0types.h"
4849

4950
// Forward declaration
5051
struct mtr_t;
5152

52-
// Forward declaration
53-
class ReadView;
54-
5553
// Forward declaration
5654
class FlushObserver;
5755

@@ -290,23 +288,6 @@ void
290288
trx_mark_sql_stat_end(
291289
/*==================*/
292290
trx_t* trx);/*!< in: trx handle */
293-
/********************************************************************//**
294-
Assigns a read view for a consistent read query. All the consistent reads
295-
within the same transaction will get the same read view, which is created
296-
when this function is first called for a new started transaction. */
297-
ReadView*
298-
trx_assign_read_view(
299-
/*=================*/
300-
trx_t* trx);/*!< in: active transaction */
301-
302-
/****************************************************************//**
303-
@return the transaction's read view or NULL if one not assigned. */
304-
UNIV_INLINE
305-
ReadView*
306-
trx_get_read_view(
307-
/*==============*/
308-
trx_t* trx);
309-
310291
/****************************************************************//**
311292
Prepares a transaction for commit/rollback. */
312293
void
@@ -571,7 +552,7 @@ Check transaction state */
571552
ut_ad(trx_state_eq((t), TRX_STATE_NOT_STARTED) \
572553
|| trx_state_eq((t), TRX_STATE_FORCED_ROLLBACK)); \
573554
ut_ad(!trx->has_logged()); \
574-
ut_ad(!MVCC::is_view_active((t)->read_view)); \
555+
ut_ad(!(t)->read_view.is_open());\
575556
ut_ad((t)->lock.wait_thr == NULL); \
576557
ut_ad(UT_LIST_GET_LEN((t)->lock.trx_locks) == 0); \
577558
ut_ad((t)->dict_operation == TRX_DICT_OP_NONE); \
@@ -1000,7 +981,7 @@ struct trx_t {
1000981

1001982
trx_state_tstate;
1002983

1003-
ReadView*read_view;/*!< consistent read view used in the
984+
ReadView read_view;/*!< consistent read view used in the
1004985
transaction, or NULL if not yet set */
1005986

1006987
UT_LIST_NODE_T(trx_t)

storage/innobase/include/trx0trx.ic

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -211,17 +211,6 @@ ok:
211211
trx->dict_operation = op;
212212
}
213213

214-
/**
215-
@param trx Get the active view for this transaction, if one exists
216-
@return the transaction's read view or NULL if one not assigned. */
217-
UNIV_INLINE
218-
ReadView*
219-
trx_get_read_view(
220-
trx_t* trx)
221-
{
222-
return(!MVCC::is_view_active(trx->read_view) ? NULL : trx->read_view);
223-
}
224-
225214
/**
226215
@param[in] trx Transaction to check
227216
@return true if the transaction is a high priority transaction.*/

storage/innobase/lock/lock0lock.cc

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,8 @@ lock_clust_rec_cons_read_sees(
415415
operate on same temp-table and so read of temp-table is
416416
always consistent read. */
417417
if (srv_read_only_mode || dict_table_is_temporary(index->table)) {
418-
ut_ad(view == 0 || dict_table_is_temporary(index->table));
418+
ut_ad(!view->is_open()
419+
|| dict_table_is_temporary(index->table));
419420
return(true);
420421
}
421422

@@ -5719,15 +5720,13 @@ lock_trx_print_wait_and_mvcc_state(
57195720

57205721
trx_print_latched(file, trx, 600);
57215722

5722-
/* Note: this read_view access is data race. Further
5723-
read_view->is_active() check is race condition. But it should
5724-
"kind of work" because read_view is freed only at shutdown.
5723+
/* Note: read_view->is_active() check is race condition. But it
5724+
should "kind of work" because read_view is freed only at shutdown.
57255725
Worst thing that may happen is that it'll get transferred to
57265726
another thread and print wrong values. */
5727-
const ReadView* read_view = trx->read_view;
57285727

5729-
if (read_view != NULL && !read_view->is_closed()) {
5730-
read_view->print_limits(file);
5728+
if (trx->read_view.is_open()) {
5729+
trx->read_view.print_limits(file);
57315730
}
57325731

57335732
if (trx->lock.que_state == TRX_QUE_LOCK_WAIT) {

0 commit comments

Comments
 (0)