diff options
Diffstat (limited to '')
-rw-r--r-- | storage/innobase/trx/trx0rseg.cc | 62 |
1 files changed, 49 insertions, 13 deletions
diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc index 87a2ac7b..964dca94 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -201,7 +201,7 @@ bool trx_rseg_read_wsrep_checkpoint(const buf_block_t *rseg_header, XID &xid) memcpy(xid.data, TRX_RSEG + TRX_RSEG_WSREP_XID_DATA + rseg_header->page.frame, XIDDATASIZE); - return true; + return wsrep_is_wsrep_xid(&xid); } /** Read the WSREP XID from the TRX_SYS page (in case of upgrade). @@ -210,6 +210,11 @@ bool trx_rseg_read_wsrep_checkpoint(const buf_block_t *rseg_header, XID &xid) @return whether the WSREP XID is present */ static bool trx_rseg_init_wsrep_xid(const page_t* page, XID& xid) { + if (memcmp(TRX_SYS + TRX_SYS_WSREP_XID_INFO + page, + field_ref_zero, TRX_SYS_WSREP_XID_LEN) == 0) { + return false; + } + if (mach_read_from_4(TRX_SYS + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_MAGIC_N_FLD + page) @@ -232,7 +237,8 @@ static bool trx_rseg_init_wsrep_xid(const page_t* page, XID& xid) memcpy(xid.data, TRX_SYS + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_DATA + page, XIDDATASIZE); - return true; + + return wsrep_is_wsrep_xid(&xid); } /** Recover the latest WSREP checkpoint XID. @@ -448,7 +454,14 @@ static dberr_t trx_rseg_mem_restore(trx_rseg_t *rseg, mtr_t *mtr) { if (!rseg->space) return DB_TABLESPACE_NOT_FOUND; + + /* Access the tablespace header page to recover rseg->space->free_limit */ + page_id_t page_id{rseg->space->id, 0}; dberr_t err; + if (!buf_page_get_gen(page_id, 0, RW_S_LATCH, nullptr, BUF_GET, mtr, &err)) + return err; + mtr->release_last_page(); + page_id.set_page_no(rseg->page_no); const buf_block_t *rseg_hdr= buf_page_get_gen(rseg->page_id(), 0, RW_S_LATCH, nullptr, BUF_GET, mtr, &err); @@ -493,10 +506,17 @@ static dberr_t trx_rseg_mem_restore(trx_rseg_t *rseg, mtr_t *mtr) trx_sys.recovered_binlog_offset= binlog_offset; trx_sys.recovered_binlog_is_legacy_pos= false; } + } #ifdef WITH_WSREP - trx_rseg_read_wsrep_checkpoint(rseg_hdr, trx_sys.recovered_wsrep_xid); + XID tmp_xid; + tmp_xid.null(); + /* Update recovered wsrep xid only if we found wsrep xid from + rseg header page and read xid seqno is larger than currently + recovered xid seqno. */ + if (trx_rseg_read_wsrep_checkpoint(rseg_hdr, tmp_xid) && + wsrep_xid_seqno(&tmp_xid) > wsrep_xid_seqno(&trx_sys.recovered_wsrep_xid)) + trx_sys.recovered_wsrep_xid.set(&tmp_xid); #endif - } } if (srv_operation == SRV_OPERATION_RESTORE) @@ -518,6 +538,11 @@ static dberr_t trx_rseg_mem_restore(trx_rseg_t *rseg, mtr_t *mtr) fil_addr_t node_addr= flst_get_last(TRX_RSEG + TRX_RSEG_HISTORY + rseg_hdr->page.frame); + if (node_addr.page >= rseg->space->free_limit || + node_addr.boffset < TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE || + node_addr.boffset >= srv_page_size - TRX_UNDO_LOG_OLD_HDR_SIZE) + return DB_CORRUPTION; + node_addr.boffset= static_cast<uint16_t>(node_addr.boffset - TRX_UNDO_HISTORY_NODE); rseg->last_page_no= node_addr.page; @@ -544,7 +569,7 @@ static dberr_t trx_rseg_mem_restore(trx_rseg_t *rseg, mtr_t *mtr) if (rseg->last_page_no != FIL_NULL) /* There is no need to cover this operation by the purge mutex because we are still bootstrapping. */ - purge_sys.purge_queue.push(*rseg); + purge_sys.enqueue(*rseg); } trx_sys.set_undo_non_empty(rseg->history_size > 0); @@ -567,10 +592,6 @@ static void trx_rseg_init_binlog_info(const page_t* page) + TRX_SYS + page); trx_sys.recovered_binlog_is_legacy_pos= true; } - -#ifdef WITH_WSREP - trx_rseg_init_wsrep_xid(page, trx_sys.recovered_wsrep_xid); -#endif } /** Initialize or recover the rollback segments at startup. */ @@ -589,7 +610,17 @@ dberr_t trx_rseg_array_init() #endif mtr_t mtr; dberr_t err = DB_SUCCESS; - + /* mariabackup --prepare only deals with the redo log and the data + files, not with transactions or the data dictionary, that's why + trx_lists_init_at_db_start() does not invoke purge_sys.create() and + purge queue mutex stays uninitialized, and trx_rseg_mem_restore() quits + before initializing undo log lists. */ + if (srv_operation != SRV_OPERATION_RESTORE) + /* Acquiring purge queue mutex here should be fine from the + deadlock prevention point of view, because executing that + function is a prerequisite for starting the purge subsystem or + any transactions. */ + purge_sys.queue_lock(); for (ulint rseg_id = 0; rseg_id < TRX_SYS_N_RSEGS; rseg_id++) { mtr.start(); if (const buf_block_t* sys = trx_sysf_get(&mtr, false)) { @@ -602,7 +633,11 @@ dberr_t trx_rseg_array_init() + sys->page.frame); trx_rseg_init_binlog_info(sys->page.frame); #ifdef WITH_WSREP - wsrep_sys_xid.set(&trx_sys.recovered_wsrep_xid); + if (trx_rseg_init_wsrep_xid( + sys->page.frame, trx_sys.recovered_wsrep_xid)) { + wsrep_sys_xid.set( + &trx_sys.recovered_wsrep_xid); + } #endif } @@ -655,7 +690,8 @@ dberr_t trx_rseg_array_init() mtr.commit(); } - + if (srv_operation != SRV_OPERATION_RESTORE) + purge_sys.queue_unlock(); if (err != DB_SUCCESS) { for (auto& rseg : trx_sys.rseg_array) { while (auto u = UT_LIST_GET_FIRST(rseg.undo_list)) { @@ -667,7 +703,7 @@ dberr_t trx_rseg_array_init() } #ifdef WITH_WSREP - if (!wsrep_sys_xid.is_null()) { + if (srv_operation == SRV_OPERATION_NORMAL && !wsrep_sys_xid.is_null()) { /* Upgrade from a version prior to 10.3.5, where WSREP XID was stored in TRX_SYS page. If no rollback segment has a WSREP XID set, |