mirror of
https://github.com/MariaDB/server.git
synced 2025-02-05 13:22:17 +01:00
![Marko Mäkelä](/assets/img/avatar_default.png)
In a Sysbench oltp_update_index workload that involves 1 table,
a serious contention between the workload and the purge of history
was observed. This was the worst when the table contained only 1 record.
This turned out to be fixed by setting innodb_purge_batch_size=128,
which corresponds to the number of usable persistent rollback segments.
When we go above that, there would be contention between row_purge_poss_sec()
and the workload, typically on the clustered index page latch, sometimes
also on a secondary index page latch. It might be that with smaller
batches, trx_sys.history_size() will end up pausing all concurrent
transaction start/commit frequently enough so that purge will be able
to make some progress, so that there would be less contention on the
index page latches between purge and SQL execution.
In commit aa719b5010
(part of MDEV-32050)
the interpretation of the parameter innodb_purge_batch_size was slightly
changed. It would correspond to the maximum desired size of the
purge_sys.pages cache. Before that change, the parameter was referring to
a number of undo log pages, but the accounting might have been inaccurate.
To avoid a regression, we will reduce the default value to
innodb_purge_batch_size=127, which will also be compatible with
innodb_undo_tablespaces>1 (which will disable rollback segment 0).
Additionally, some logic in the purge and MVCC checks is simplified.
The purge tasks will make use of purge_sys.pages when accessing undo
log pages to find out if a secondary index record can be removed.
If an undo page needs to be looked up in buf_pool.page_hash, we will
merely buffer-fix it. This is correct, because the undo pages are
append-only in nature. Holding purge_sys.latch or purge_sys.end_latch
or the fact that the current thread is executing as a part of an
in-progress purge batch will prevent the contents of the undo page from
being freed and subsequently reused. The buffer-fix will prevent the
page from being evicted form the buffer pool. Thanks to this logic,
we can refer to the undo log record directly in the buffer pool page
and avoid copying the record.
buf_pool_t::page_fix(): Look up and buffer-fix a page. This is useful
for accessing undo log pages, which are append-only by nature.
There will be no need to deal with change buffer or ROW_FORMAT=COMPRESSED
in that case.
purge_sys_t::view_guard::view_guard(): Allow the type of guard to be
acquired: end_latch, latch, or no latch (in case we are a purge thread).
purge_sys_t::view_guard::get(): Read-only accessor to purge_sys.pages.
purge_sys_t::get_page(): Invoke buf_pool_t::page_fix().
row_vers_old_has_index_entry(): Replaced with row_purge_is_unsafe()
and row_undo_mod_sec_unsafe().
trx_undo_get_undo_rec(): Merged to trx_undo_prev_version_build().
row_purge_poss_sec(): Add the parameter mtr and remove redundant
or unused parameters sec_pcur, sec_mtr, is_tree. We will use the
caller's mtr object but release any acquired page latches before
returning.
btr_cur_get_page(), page_cur_get_page(): Do not invoke page_align().
row_purge_remove_sec_if_poss_leaf(): Return the value of PAGE_MAX_TRX_ID
to be checked against the page in row_purge_remove_sec_if_poss_tree().
If the secondary index page was not changed meanwhile, it will be
unnecessary to invoke row_purge_poss_sec() again.
trx_undo_prev_version_build(): Access any undo log pages using
the caller's mini-transaction object.
row_purge_vc_matches_cluster(): Moved to the only compilation unit that
needs it.
Reviewed by: Debarun Banerjee
158 lines
6 KiB
C++
158 lines
6 KiB
C++
/*****************************************************************************
|
|
|
|
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
|
Copyright (c) 2017, 2022, MariaDB Corporation.
|
|
|
|
This program is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License as published by the Free Software
|
|
Foundation; version 2 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
this program; if not, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
|
|
|
|
*****************************************************************************/
|
|
|
|
/**************************************************//**
|
|
@file include/row0vers.h
|
|
Row versions
|
|
|
|
Created 2/6/1997 Heikki Tuuri
|
|
*******************************************************/
|
|
|
|
#ifndef row0vers_h
|
|
#define row0vers_h
|
|
|
|
#include "data0data.h"
|
|
#include "trx0types.h"
|
|
#include "que0types.h"
|
|
#include "rem0types.h"
|
|
#include "mtr0mtr.h"
|
|
#include "dict0mem.h"
|
|
#include "row0types.h"
|
|
|
|
// Forward declaration
|
|
class ReadView;
|
|
|
|
/** Determine if an active transaction has inserted or modified a secondary
|
|
index record.
|
|
@param[in,out] caller_trx trx of current thread
|
|
@param[in] rec secondary index record
|
|
@param[in] index secondary index
|
|
@param[in] offsets rec_get_offsets(rec, index)
|
|
@return the active transaction; state must be rechecked after
|
|
acquiring trx->mutex, and trx->release_reference() must be invoked
|
|
@retval NULL if the record was committed */
|
|
trx_t*
|
|
row_vers_impl_x_locked(
|
|
trx_t* caller_trx,
|
|
const rec_t* rec,
|
|
dict_index_t* index,
|
|
const rec_offs* offsets);
|
|
|
|
/** Find out whether data tuple has missing data type
|
|
for indexed virtual column.
|
|
@param tuple data tuple
|
|
@param index virtual index
|
|
@return true if tuple has missing column type */
|
|
bool dtuple_vcol_data_missing(const dtuple_t &tuple,
|
|
const dict_index_t &index);
|
|
/** build virtual column value from current cluster index record data
|
|
@param[in,out] row the cluster index row in dtuple form
|
|
@param[in] clust_index clustered index
|
|
@param[in] index the secondary index
|
|
@param[in] heap heap used to build virtual dtuple. */
|
|
bool
|
|
row_vers_build_clust_v_col(
|
|
dtuple_t* row,
|
|
dict_index_t* clust_index,
|
|
dict_index_t* index,
|
|
mem_heap_t* heap);
|
|
/** Build a dtuple contains virtual column data for current cluster index
|
|
@param[in] rec cluster index rec
|
|
@param[in] clust_index cluster index
|
|
@param[in] clust_offsets cluster rec offset
|
|
@param[in] index secondary index
|
|
@param[in] trx_id transaction ID on the purging record,
|
|
or 0 if called outside purge
|
|
@param[in] roll_ptr roll_ptr for the purge record
|
|
@param[in,out] heap heap memory
|
|
@param[in,out] v_heap heap memory to keep virtual column tuple
|
|
@param[in,out] mtr mini-transaction
|
|
@return dtuple contains virtual column data */
|
|
dtuple_t*
|
|
row_vers_build_cur_vrow(
|
|
const rec_t* rec,
|
|
dict_index_t* clust_index,
|
|
rec_offs** clust_offsets,
|
|
dict_index_t* index,
|
|
trx_id_t trx_id,
|
|
roll_ptr_t roll_ptr,
|
|
mem_heap_t* heap,
|
|
mem_heap_t* v_heap,
|
|
mtr_t* mtr);
|
|
|
|
/*****************************************************************//**
|
|
Constructs the version of a clustered index record which a consistent
|
|
read should see. We assume that the trx id stored in rec is such that
|
|
the consistent read should not see rec in its present version.
|
|
@return error code
|
|
@retval DB_SUCCESS if a previous version was fetched
|
|
@retval DB_MISSING_HISTORY if the history is missing (a sign of corruption) */
|
|
dberr_t
|
|
row_vers_build_for_consistent_read(
|
|
/*===============================*/
|
|
const rec_t* rec, /*!< in: record in a clustered index; the
|
|
caller must have a latch on the page; this
|
|
latch locks the top of the stack of versions
|
|
of this records */
|
|
mtr_t* mtr, /*!< in: mtr holding the latch on rec; it will
|
|
also hold the latch on purge_view */
|
|
dict_index_t* index, /*!< in: the clustered index */
|
|
rec_offs** offsets,/*!< in/out: offsets returned by
|
|
rec_get_offsets(rec, index) */
|
|
ReadView* view, /*!< in: the consistent read view */
|
|
mem_heap_t** offset_heap,/*!< in/out: memory heap from which
|
|
the offsets are allocated */
|
|
mem_heap_t* in_heap,/*!< in: memory heap from which the memory for
|
|
*old_vers is allocated; memory for possible
|
|
intermediate versions is allocated and freed
|
|
locally within the function */
|
|
rec_t** old_vers,/*!< out, own: old version, or NULL
|
|
if the history is missing or the record
|
|
does not exist in the view, that is,
|
|
it was freshly inserted afterwards */
|
|
dtuple_t** vrow); /*!< out: reports virtual column info if any */
|
|
|
|
/*****************************************************************//**
|
|
Constructs the last committed version of a clustered index record,
|
|
which should be seen by a semi-consistent read. */
|
|
void
|
|
row_vers_build_for_semi_consistent_read(
|
|
/*====================================*/
|
|
trx_t* caller_trx,/*!<in/out: trx of current thread */
|
|
const rec_t* rec, /*!< in: record in a clustered index; the
|
|
caller must have a latch on the page; this
|
|
latch locks the top of the stack of versions
|
|
of this records */
|
|
mtr_t* mtr, /*!< in: mtr holding the latch on rec */
|
|
dict_index_t* index, /*!< in: the clustered index */
|
|
rec_offs** offsets,/*!< in/out: offsets returned by
|
|
rec_get_offsets(rec, index) */
|
|
mem_heap_t** offset_heap,/*!< in/out: memory heap from which
|
|
the offsets are allocated */
|
|
mem_heap_t* in_heap,/*!< in: memory heap from which the memory for
|
|
*old_vers is allocated; memory for possible
|
|
intermediate versions is allocated and freed
|
|
locally within the function */
|
|
const rec_t** old_vers,/*!< out: rec, old version, or NULL if the
|
|
record does not exist in the view, that is,
|
|
it was freshly inserted afterwards */
|
|
dtuple_t** vrow); /*!< out: holds virtual column info if any
|
|
is updated in the view */
|
|
|
|
#endif
|