diff options
Diffstat (limited to 'storage/innobase/trx/trx0rseg.cc')
-rw-r--r-- | storage/innobase/trx/trx0rseg.cc | 110 |
1 files changed, 67 insertions, 43 deletions
diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc index 10092375ebd..a57a78b9408 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -43,6 +43,33 @@ static long long wsrep_seqno = -1; /** The latest known WSREP XID UUID */ static unsigned char wsrep_uuid[16]; +/** Write the WSREP XID information into rollback segment header. +@param[in,out] rseg_header rollback segment header +@param[in] xid WSREP XID +@param[in,out] mtr mini transaction */ +static void +trx_rseg_write_wsrep_checkpoint( + trx_rsegf_t* rseg_header, + const XID* xid, + mtr_t* mtr) +{ + mlog_write_ulint(TRX_RSEG_WSREP_XID_FORMAT + rseg_header, + uint32_t(xid->formatID), + MLOG_4BYTES, mtr); + + mlog_write_ulint(TRX_RSEG_WSREP_XID_GTRID_LEN + rseg_header, + uint32_t(xid->gtrid_length), + MLOG_4BYTES, mtr); + + mlog_write_ulint(TRX_RSEG_WSREP_XID_BQUAL_LEN + rseg_header, + uint32_t(xid->bqual_length), + MLOG_4BYTES, mtr); + + mlog_write_string(TRX_RSEG_WSREP_XID_DATA + rseg_header, + reinterpret_cast<const byte*>(xid->data), + XIDDATASIZE, mtr); +} + /** Update the WSREP XID information in rollback segment header. @param[in,out] rseg_header rollback segment header @param[in] xid WSREP XID @@ -60,29 +87,28 @@ trx_rseg_update_wsrep_checkpoint( long long xid_seqno = wsrep_xid_seqno(xid); const byte* xid_uuid = wsrep_xid_uuid(xid); - if (!memcmp(xid_uuid, wsrep_uuid, sizeof wsrep_uuid)) { + if (xid_seqno != -1 + && !memcmp(xid_uuid, wsrep_uuid, sizeof wsrep_uuid)) { ut_ad(xid_seqno > wsrep_seqno); } else { memcpy(wsrep_uuid, xid_uuid, sizeof wsrep_uuid); } wsrep_seqno = xid_seqno; #endif /* UNIV_DEBUG */ + trx_rseg_write_wsrep_checkpoint(rseg_header, xid, mtr); +} - mlog_write_ulint(TRX_RSEG_WSREP_XID_FORMAT + rseg_header, - uint32_t(xid->formatID), - MLOG_4BYTES, mtr); - - mlog_write_ulint(TRX_RSEG_WSREP_XID_GTRID_LEN + rseg_header, - uint32_t(xid->gtrid_length), - MLOG_4BYTES, mtr); - - mlog_write_ulint(TRX_RSEG_WSREP_XID_BQUAL_LEN + rseg_header, - uint32_t(xid->bqual_length), - MLOG_4BYTES, mtr); - - mlog_write_string(TRX_RSEG_WSREP_XID_DATA + rseg_header, - reinterpret_cast<const byte*>(xid->data), - XIDDATASIZE, mtr); +/** Clear the WSREP XID information from rollback segment header. +@param[in,out] rseg_header Rollback segment header +@param[in,out] mtr mini-transaction */ +static void +trx_rseg_clear_wsrep_checkpoint( + trx_rsegf_t* rseg_header, + mtr_t* mtr) +{ + mlog_memset(rseg_header + TRX_RSEG_WSREP_XID_INFO, + TRX_RSEG_WSREP_XID_DATA + XIDDATASIZE + - TRX_RSEG_WSREP_XID_INFO, 0, mtr); } /** Update WSREP checkpoint XID in first rollback segment header @@ -97,6 +123,13 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid) mtr_t mtr; mtr.start(); + const byte* xid_uuid = wsrep_xid_uuid(xid); + /* We must make check against wsrep_uuid here, the + trx_rseg_update_wsrep_checkpoint() writes over wsrep_uuid with + xid contents in debug mode and the memcmp() will never give nonzero + result. */ + const bool must_clear_rsegs = memcmp(wsrep_uuid, xid_uuid, + sizeof wsrep_uuid); const trx_rseg_t* rseg = trx_sys.rseg_array[0]; trx_rsegf_t* rseg_header = trx_rsegf_get(rseg->space, rseg->page_no, @@ -107,10 +140,7 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid) trx_rseg_update_wsrep_checkpoint(rseg_header, xid, &mtr); - const byte* xid_uuid = wsrep_xid_uuid(xid); - if (memcmp(wsrep_uuid, xid_uuid, sizeof wsrep_uuid)) { - memcpy(wsrep_uuid, xid_uuid, sizeof wsrep_uuid); - + if (must_clear_rsegs) { /* Because the UUID part of the WSREP XID differed from current_xid_uuid, the WSREP group UUID was changed, and we must reset the XID in all rollback @@ -118,10 +148,11 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid) for (ulint rseg_id = 1; rseg_id < TRX_SYS_N_RSEGS; ++rseg_id) { if (const trx_rseg_t* rseg = trx_sys.rseg_array[rseg_id]) { - trx_rseg_update_wsrep_checkpoint( + trx_rseg_clear_wsrep_checkpoint( trx_rsegf_get(rseg->space, - rseg->page_no, &mtr), - xid, &mtr); + rseg->page_no, + &mtr), + &mtr); } } } @@ -252,12 +283,10 @@ void trx_rseg_format_upgrade(trx_rsegf_t* rseg_header, mtr_t* mtr) mlog_write_ulint(rseg_format, 0, MLOG_4BYTES, mtr); /* Clear also possible garbage at the end of the page. Old InnoDB versions did not initialize unused parts of pages. */ - byte* b = rseg_header + TRX_RSEG_MAX_TRX_ID + 8; - ulint len = srv_page_size - - (FIL_PAGE_DATA_END - + TRX_RSEG + TRX_RSEG_MAX_TRX_ID + 8); - memset(b, 0, len); - mlog_log_string(b, len, mtr); + mlog_memset(TRX_RSEG_MAX_TRX_ID + 8 + rseg_header, + srv_page_size + - (FIL_PAGE_DATA_END + + TRX_RSEG + TRX_RSEG_MAX_TRX_ID + 8), 0, mtr); } /** Create a rollback segment header. @@ -289,22 +318,17 @@ trx_rseg_header_create( buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW); - mlog_write_ulint(TRX_RSEG + TRX_RSEG_FORMAT + block->frame, 0, - MLOG_4BYTES, mtr); + ut_ad(0 == mach_read_from_4(TRX_RSEG_FORMAT + TRX_RSEG + + block->frame)); + ut_ad(0 == mach_read_from_4(TRX_RSEG_HISTORY_SIZE + TRX_RSEG + + block->frame)); /* Initialize the history list */ - - mlog_write_ulint(TRX_RSEG + TRX_RSEG_HISTORY_SIZE + block->frame, 0, - MLOG_4BYTES, mtr); - flst_init(TRX_RSEG + TRX_RSEG_HISTORY + block->frame, mtr); - trx_rsegf_t* rsegf = TRX_RSEG + block->frame; + flst_init(block, TRX_RSEG_HISTORY + TRX_RSEG, mtr); /* Reset the undo log slots */ - for (ulint i = 0; i < TRX_RSEG_N_SLOTS; i++) { - /* This is generating a lot of redo log. MariaDB 10.4 - introduced MLOG_MEMSET to reduce the redo log volume. */ - trx_rsegf_set_nth_undo(rsegf, i, FIL_NULL, mtr); - } + mlog_memset(block, TRX_RSEG_UNDO_SLOTS + TRX_RSEG, + TRX_RSEG_N_SLOTS * 4, 0xff, mtr); if (sys_header) { /* Add the rollback segment info to the free slot in @@ -475,8 +499,8 @@ trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr) rseg->curr_size = mach_read_from_4(rseg_header + TRX_RSEG_HISTORY_SIZE) + 1 + trx_undo_lists_init(rseg, max_trx_id, rseg_header); - if (ulint len = flst_get_len(rseg_header + TRX_RSEG_HISTORY)) { - trx_sys.history_add(int32(len)); + if (auto len = flst_get_len(rseg_header + TRX_RSEG_HISTORY)) { + trx_sys.rseg_history_len += len; fil_addr_t node_addr = trx_purge_get_log_from_hist( flst_get_last(rseg_header + TRX_RSEG_HISTORY, mtr)); |