234 lines
7.8 KiB
Plaintext
234 lines
7.8 KiB
Plaintext
/*****************************************************************************
|
|
|
|
Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License, version 2.0, as published by the
|
|
Free Software Foundation.
|
|
|
|
This program is also distributed with certain software (including but not
|
|
limited to OpenSSL) that is licensed under separate terms, as designated in a
|
|
particular file or component or in included license documentation. The authors
|
|
of MySQL hereby grant you an additional permission to link the program and
|
|
your derivative works with the separately licensed software that they have
|
|
included with MySQL.
|
|
|
|
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, version 2.0,
|
|
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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*****************************************************************************/
|
|
|
|
/** @file include/trx0rseg.ic
|
|
Rollback segment
|
|
|
|
Created 3/26/1996 Heikki Tuuri
|
|
*******************************************************/
|
|
|
|
#include "mtr0log.h"
|
|
#include "srv0srv.h"
|
|
#include "trx0purge.h"
|
|
#include "trx0sys.h"
|
|
|
|
/** Gets a rollback segment header.
|
|
@param[in] space space where placed
|
|
@param[in] page_no page number of the header
|
|
@param[in] page_size page size
|
|
@param[in,out] mtr mini-transaction
|
|
@return rollback segment header, page x-latched */
|
|
UNIV_INLINE
|
|
trx_rsegf_t *trx_rsegf_get(space_id_t space, page_no_t page_no,
|
|
const page_size_t &page_size, mtr_t *mtr) {
|
|
buf_block_t *block;
|
|
trx_rsegf_t *header;
|
|
|
|
block = buf_page_get(page_id_t(space, page_no), page_size, RW_X_LATCH, mtr);
|
|
|
|
buf_block_dbg_add_level(block, SYNC_RSEG_HEADER);
|
|
|
|
header = TRX_RSEG + buf_block_get_frame(block);
|
|
|
|
return (header);
|
|
}
|
|
|
|
/** Gets a newly created rollback segment header.
|
|
@param[in] space space where placed
|
|
@param[in] page_no page number of the header
|
|
@param[in] page_size page size
|
|
@param[in,out] mtr mini-transaction
|
|
@return rollback segment header, page x-latched */
|
|
UNIV_INLINE
|
|
trx_rsegf_t *trx_rsegf_get_new(space_id_t space, page_no_t page_no,
|
|
const page_size_t &page_size, mtr_t *mtr) {
|
|
buf_block_t *block;
|
|
trx_rsegf_t *header;
|
|
|
|
block = buf_page_get(page_id_t(space, page_no), page_size, RW_X_LATCH, mtr);
|
|
|
|
buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW);
|
|
|
|
header = TRX_RSEG + buf_block_get_frame(block);
|
|
|
|
return (header);
|
|
}
|
|
|
|
/** Gets the file page number of the nth undo log slot.
|
|
@return page number of the undo log segment */
|
|
UNIV_INLINE
|
|
page_no_t trx_rsegf_get_nth_undo(
|
|
trx_rsegf_t *rsegf, /*!< in: rollback segment header */
|
|
ulint n, /*!< in: index of slot */
|
|
mtr_t *mtr) /*!< in: mtr */
|
|
{
|
|
ut_a(n < TRX_RSEG_N_SLOTS);
|
|
|
|
return (mtr_read_ulint(rsegf + TRX_RSEG_UNDO_SLOTS + n * TRX_RSEG_SLOT_SIZE,
|
|
MLOG_4BYTES, mtr));
|
|
}
|
|
|
|
/** Sets the file page number of the nth undo log slot. */
|
|
UNIV_INLINE
|
|
void trx_rsegf_set_nth_undo(
|
|
trx_rsegf_t *rsegf, /*!< in: rollback segment header */
|
|
ulint n, /*!< in: index of slot */
|
|
page_no_t page_no, /*!< in: page number of the undo log segment */
|
|
mtr_t *mtr) /*!< in: mtr */
|
|
{
|
|
ut_a(n < TRX_RSEG_N_SLOTS);
|
|
|
|
mlog_write_ulint(rsegf + TRX_RSEG_UNDO_SLOTS + n * TRX_RSEG_SLOT_SIZE,
|
|
page_no, MLOG_4BYTES, mtr);
|
|
}
|
|
|
|
/** Looks for a free slot for an undo log segment.
|
|
@return slot index or ULINT_UNDEFINED if not found */
|
|
UNIV_INLINE
|
|
ulint trx_rsegf_undo_find_free(
|
|
trx_rsegf_t *rsegf, /*!< in: rollback segment header */
|
|
mtr_t *mtr) /*!< in: mtr */
|
|
{
|
|
ulint i;
|
|
page_no_t page_no;
|
|
ulint max_slots = TRX_RSEG_N_SLOTS;
|
|
|
|
#ifdef UNIV_DEBUG
|
|
if (trx_rseg_n_slots_debug) {
|
|
max_slots = ut_min(static_cast<ulint>(trx_rseg_n_slots_debug),
|
|
static_cast<ulint>(TRX_RSEG_N_SLOTS));
|
|
}
|
|
#endif
|
|
|
|
for (i = 0; i < max_slots; i++) {
|
|
page_no = trx_rsegf_get_nth_undo(rsegf, i, mtr);
|
|
|
|
if (page_no == FIL_NULL) {
|
|
return (i);
|
|
}
|
|
}
|
|
|
|
return (ULINT_UNDEFINED);
|
|
}
|
|
|
|
/** Convert a 7-bit ID stored in a rollback pointer to an undo space ID.
|
|
Before 8.0, this ID is called an rseg_id and is a slot in the TRX_SYS page
|
|
where the space_id can be read.
|
|
After 8.0 this is an undo space number which can be converted directly to
|
|
an undo space ID.
|
|
@param[in] id a 7-bit ID from a rollback pointer
|
|
@param[in] is_temp true if rseg from Temp Tablespace else false.
|
|
@return undo tablespace ID containing the rollback segment */
|
|
inline space_id_t trx_rseg_id_to_space_id(ulint id, bool is_temp) {
|
|
/* The rseg_id must be an undo_space_num between 0 and 127. */
|
|
ut_ad(id < TRX_SYS_N_RSEGS);
|
|
|
|
/* MySQL versions before v5.7.2 used the first 32 slots in the
|
|
TRX_SYS page for redo rollback segments. v5.7.2 uses these seg_ids
|
|
for no-redo rollback segments in the temporary tablespace.
|
|
v8 will once again use them for durable/redo rollback segments. */
|
|
if (is_temp) {
|
|
return (srv_tmp_space.space_id());
|
|
}
|
|
|
|
/* If the ID is 0 then use the system tablespace. */
|
|
if (id == 0) {
|
|
return (TRX_SYS_SPACE);
|
|
}
|
|
|
|
if (srv_upgrade_old_undo_found) {
|
|
/* Interpret the id as a slot in the TRX_SYS page. */
|
|
trx_rseg_t *rseg = trx_sys->rsegs.find(id);
|
|
return (rseg->space_id);
|
|
}
|
|
|
|
/* We assume at this point that all undo tablespaces have
|
|
reserved space_ids and RSEG_ARRAY pages. */
|
|
ut_ad(!undo::spaces->empty());
|
|
|
|
/* The space_id_bank for this slot cannot change since this call is done
|
|
by purge or MVCC. This space_id can only change during truncate when
|
|
there are no more undo logs in this undo tablespace. */
|
|
space_id_t space_id = undo::num2id(static_cast<space_id_t>(id));
|
|
ut_ad(space_id != SPACE_UNKNOWN);
|
|
|
|
return (space_id);
|
|
}
|
|
|
|
/** Get a pointer to the rollback segment directory header and x-latches its
|
|
page.
|
|
@param[in] space_id Undo Tablespace ID
|
|
@param[in] mtr mtr
|
|
@return pointer to rollback segment directory header with page x-latched. */
|
|
inline trx_rsegsf_t *trx_rsegsf_get(space_id_t space_id, mtr_t *mtr) {
|
|
buf_block_t *block;
|
|
trx_rsegsf_t *rsegs_header;
|
|
|
|
ut_ad(mtr != nullptr);
|
|
ut_ad(undo::is_reserved(space_id));
|
|
|
|
block = buf_page_get(page_id_t(space_id, FSP_RSEG_ARRAY_PAGE_NO),
|
|
univ_page_size, RW_X_LATCH, mtr);
|
|
buf_block_dbg_add_level(block, SYNC_RSEG_ARRAY_HEADER);
|
|
|
|
rsegs_header = RSEG_ARRAY_HEADER + buf_block_get_frame(block);
|
|
|
|
return (rsegs_header);
|
|
}
|
|
|
|
/** Get the page number of the nth rollback segment slot in the
|
|
RSEG_ARRAY page for this undo tablespace.
|
|
@param[in] rsegs_header rollback segment array page header
|
|
@param[in] slot slot index == rseg id
|
|
@param[in] mtr mtr
|
|
@return page number, FIL_NULL if slot unused */
|
|
inline page_no_t trx_rsegsf_get_page_no(trx_rsegsf_t *rsegs_header, ulint slot,
|
|
mtr_t *mtr) {
|
|
ut_ad(rsegs_header != nullptr);
|
|
ut_ad(mtr != nullptr);
|
|
ut_ad(slot < FSP_MAX_ROLLBACK_SEGMENTS);
|
|
|
|
return (mtr_read_ulint(
|
|
rsegs_header + RSEG_ARRAY_PAGES_OFFSET + slot * RSEG_ARRAY_SLOT_SIZE,
|
|
MLOG_4BYTES, mtr));
|
|
}
|
|
|
|
/** Sets the page number of the nth rollback segment slot in the
|
|
independent undo tablespace.
|
|
@param[in] rsegs_header rollback segment array page header
|
|
@param[in] slot slot number on page == rseg id
|
|
@param[in] page_no rollback regment header page number
|
|
@param[in] mtr mtr */
|
|
UNIV_INLINE
|
|
void trx_rsegsf_set_page_no(trx_rsegsf_t *rsegs_header, ulint slot,
|
|
page_no_t page_no, mtr_t *mtr) {
|
|
ut_ad(rsegs_header);
|
|
|
|
mlog_write_ulint(
|
|
rsegs_header + RSEG_ARRAY_PAGES_OFFSET + slot * RSEG_ARRAY_SLOT_SIZE,
|
|
page_no, MLOG_4BYTES, mtr);
|
|
}
|