mirror of
https://github.com/MariaDB/server.git
synced 2026-05-16 20:07:13 +02:00
MDEV-15132 Avoid accessing the TRX_SYS page
InnoDB maintains an internal persistent sequence of transaction identifiers. This sequence is used for assigning both transaction start identifiers (DB_TRX_ID=trx->id) and end identifiers (trx->no) as well as end identifiers for the mysql.transaction_registry table that was introduced in MDEV-12894. TRX_SYS_TRX_ID_WRITE_MARGIN: Remove. After this many updates of the sequence we used to update the TRX_SYS page. We can avoid accessing the TRX_SYS page if we modify the InnoDB startup so that resurrecting the sequence from other pages of the transaction system. TRX_SYS_TRX_ID_STORE: Deprecate. The field only exists for the purpose of upgrading from an earlier version of MySQL or MariaDB. Starting with this fix, MariaDB will rely on the fields TRX_UNDO_TRX_ID, TRX_UNDO_TRX_NO in the undo log header page of each non-committed transaction, and on the new field TRX_RSEG_MAX_TRX_ID in rollback segment header pages. Because of this change, setting innodb_force_recovery=5 or 6 may cause the system to recover with trx_sys.get_max_trx_id()==0. We must adjust checks for invalid DB_TRX_ID and PAGE_MAX_TRX_ID accordingly. We will change the startup and shutdown messages to display the trx_sys.get_max_trx_id() in addition to the log sequence number. trx_sys_t::flush_max_trx_id(): Remove. trx_undo_mem_create_at_db_start(), trx_undo_lists_init(): Add an output parameter max_trx_id, to be updated from TRX_UNDO_TRX_ID, TRX_UNDO_TRX_NO. TRX_RSEG_MAX_TRX_ID: New field, for persisting trx_sys.get_max_trx_id() at the time of the latest transaction commit. Startup is not reading the undo log pages of committed transactions. We want to avoid additional page accesses on startup, as well as trouble when all undo logs have been emptied. On startup, we will simply determine the maximum value from all pages that are being read anyway. TRX_RSEG_FORMAT: Redefined from TRX_RSEG_MAX_SIZE. Old versions of InnoDB wrote uninitialized garbage to unused data fields. Because of this, we cannot simply introduce a new field in the rollback segment pages and expect it to be always zero, like it would if the database was created by a recent enough InnoDB version. Luckily, it looks like the field TRX_RSEG_MAX_SIZE was always written as 0xfffffffe. We will indicate a new subformat of the page by writing 0 to this field. This has the nice side effect that after a downgrade to older versions of InnoDB, transactions should fail to allocate any undo log, that is, writes will be blocked. So, there is no problem of getting corrupted transaction identifiers after downgrading. trx_rseg_t::max_size: Remove. trx_rseg_header_create(): Remove the parameter max_size=ULINT_MAX. trx_purge_add_undo_to_history(): Update TRX_RSEG_MAX_SIZE (and TRX_RSEG_FORMAT if needed). This is invoked on transaction commit. trx_rseg_mem_restore(): If TRX_RSEG_FORMAT contains 0, read TRX_RSEG_MAX_SIZE. trx_rseg_array_init(): Invoke trx_sys.init_max_trx_id(max_trx_id + 1) where max_trx_id was the maximum that was encountered in the rollback segment pages and the undo log pages of recovered active, XA PREPARE, or some committed transactions. (See trx_purge_add_undo_to_history() which invokes trx_rsegf_set_nth_undo(..., FIL_NULL, ...); not all committed transactions will be immediately detached from the rollback segment header.)
This commit is contained in:
parent
bb441ca4ad
commit
c7d0448797
11 changed files with 104 additions and 166 deletions
|
|
@ -780,9 +780,6 @@ trx_undo_add_page(trx_t* trx, trx_undo_t* undo, mtr_t* mtr)
|
|||
counterpart of the tree latch, which is the rseg mutex. */
|
||||
|
||||
mutex_enter(&rseg->mutex);
|
||||
if (rseg->curr_size == rseg->max_size) {
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
header_page = trx_undo_page_get(
|
||||
page_id_t(undo->space, undo->hdr_page_no), mtr);
|
||||
|
|
@ -893,34 +890,6 @@ trx_undo_free_last_page(trx_undo_t* undo, mtr_t* mtr)
|
|||
undo->size--;
|
||||
}
|
||||
|
||||
/** Empties an undo log header page of undo records for that undo log.
|
||||
Other undo logs may still have records on that page, if it is an update
|
||||
undo log.
|
||||
@param[in] space space
|
||||
@param[in] hdr_page_no header page number
|
||||
@param[in] hdr_offset header offset
|
||||
@param[in,out] mtr mini-transaction */
|
||||
static
|
||||
void
|
||||
trx_undo_empty_header_page(
|
||||
ulint space,
|
||||
ulint hdr_page_no,
|
||||
ulint hdr_offset,
|
||||
mtr_t* mtr)
|
||||
{
|
||||
page_t* header_page;
|
||||
trx_ulogf_t* log_hdr;
|
||||
ulint end;
|
||||
|
||||
header_page = trx_undo_page_get(page_id_t(space, hdr_page_no), mtr);
|
||||
|
||||
log_hdr = header_page + hdr_offset;
|
||||
|
||||
end = trx_undo_page_get_end(header_page, hdr_page_no, hdr_offset);
|
||||
|
||||
mlog_write_ulint(log_hdr + TRX_UNDO_LOG_START, end, MLOG_2BYTES, mtr);
|
||||
}
|
||||
|
||||
/** Truncate the tail of an undo log during rollback.
|
||||
@param[in,out] undo undo log
|
||||
@param[in] limit all undo logs after this limit will be discarded
|
||||
|
|
@ -1032,9 +1001,16 @@ loop:
|
|||
page_no = page_get_page_no(undo_page);
|
||||
|
||||
if (page_no == hdr_page_no) {
|
||||
trx_undo_empty_header_page(rseg->space,
|
||||
hdr_page_no, hdr_offset,
|
||||
&mtr);
|
||||
uint16_t end = mach_read_from_2(hdr_offset + TRX_UNDO_NEXT_LOG
|
||||
+ undo_page);
|
||||
if (end == 0) {
|
||||
end = mach_read_from_2(TRX_UNDO_PAGE_HDR
|
||||
+ TRX_UNDO_PAGE_FREE
|
||||
+ undo_page);
|
||||
}
|
||||
|
||||
mlog_write_ulint(undo_page + hdr_offset + TRX_UNDO_LOG_START,
|
||||
end, MLOG_2BYTES, &mtr);
|
||||
} else {
|
||||
trx_undo_free_page(rseg, TRUE, rseg->space, hdr_page_no,
|
||||
page_no, &mtr);
|
||||
|
|
@ -1100,12 +1076,14 @@ trx_undo_seg_free(
|
|||
/*========== UNDO LOG MEMORY COPY INITIALIZATION =====================*/
|
||||
|
||||
/** Read an undo log when starting up the database.
|
||||
@param[in,out] rseg rollback segment
|
||||
@param[in] id rollback segment slot
|
||||
@param[in] page_no undo log segment page number
|
||||
@param[in,out] rseg rollback segment
|
||||
@param[in] id rollback segment slot
|
||||
@param[in] page_no undo log segment page number
|
||||
@param[in,out] max_trx_id the largest observed transaction ID
|
||||
@return size of the undo log in pages */
|
||||
ulint
|
||||
trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no)
|
||||
trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no,
|
||||
trx_id_t& max_trx_id)
|
||||
{
|
||||
mtr_t mtr;
|
||||
XID xid;
|
||||
|
|
@ -1135,10 +1113,19 @@ trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no)
|
|||
xid.null();
|
||||
}
|
||||
|
||||
trx_id_t trx_id = mach_read_from_8(undo_header + TRX_UNDO_TRX_NO);
|
||||
if (trx_id > max_trx_id) {
|
||||
max_trx_id = trx_id;
|
||||
}
|
||||
|
||||
trx_id = mach_read_from_8(undo_header + TRX_UNDO_TRX_ID);
|
||||
if (trx_id > max_trx_id) {
|
||||
max_trx_id = trx_id;
|
||||
}
|
||||
|
||||
mutex_enter(&rseg->mutex);
|
||||
trx_undo_t* undo = trx_undo_mem_create(
|
||||
rseg, id, mach_read_from_8(undo_header + TRX_UNDO_TRX_ID),
|
||||
&xid, page_no, offset);
|
||||
rseg, id, trx_id, &xid, page_no, offset);
|
||||
mutex_exit(&rseg->mutex);
|
||||
|
||||
undo->dict_operation = undo_header[TRX_UNDO_DICT_TRANS];
|
||||
|
|
@ -1293,11 +1280,6 @@ trx_undo_create(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** undo,
|
|||
|
||||
ut_ad(mutex_own(&(rseg->mutex)));
|
||||
|
||||
if (rseg->curr_size == rseg->max_size) {
|
||||
*err = DB_OUT_OF_FILE_SPACE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf_block_t* block = trx_undo_seg_create(
|
||||
trx_rsegf_get(rseg->space, rseg->page_no, mtr), &id, err, mtr);
|
||||
|
||||
|
|
@ -1754,7 +1736,7 @@ trx_undo_truncate_tablespace(
|
|||
trx_rseg_t* rseg = undo_trunc->get_ith_rseg(i);
|
||||
|
||||
rseg->page_no = trx_rseg_header_create(
|
||||
space_id, ULINT_MAX, rseg->id, sys_header, &mtr);
|
||||
space_id, rseg->id, sys_header, &mtr);
|
||||
|
||||
rseg_header = trx_rsegf_get_new(space_id, rseg->page_no, &mtr);
|
||||
|
||||
|
|
@ -1777,9 +1759,6 @@ trx_undo_truncate_tablespace(
|
|||
UT_LIST_INIT(rseg->undo_list, &trx_undo_t::undo_list);
|
||||
UT_LIST_INIT(rseg->undo_cached, &trx_undo_t::undo_list);
|
||||
|
||||
rseg->max_size = mtr_read_ulint(
|
||||
rseg_header + TRX_RSEG_MAX_SIZE, MLOG_4BYTES, &mtr);
|
||||
|
||||
/* Initialize the undo log lists according to the rseg header */
|
||||
rseg->curr_size = mtr_read_ulint(
|
||||
rseg_header + TRX_RSEG_HISTORY_SIZE, MLOG_4BYTES, &mtr)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue