summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
Diffstat (limited to 'storage')
-rw-r--r--storage/innobase/include/srv0start.h7
-rw-r--r--storage/innobase/include/trx0rseg.h7
-rw-r--r--storage/innobase/include/trx0sys.h16
-rw-r--r--storage/innobase/srv/srv0start.cc306
-rw-r--r--storage/innobase/trx/trx0purge.cc4
-rw-r--r--storage/innobase/trx/trx0rseg.cc64
-rw-r--r--storage/innobase/trx/trx0sys.cc5
-rw-r--r--storage/innobase/trx/trx0trx.cc12
8 files changed, 350 insertions, 71 deletions
diff --git a/storage/innobase/include/srv0start.h b/storage/innobase/include/srv0start.h
index 44b19aa666b..1372959d184 100644
--- a/storage/innobase/include/srv0start.h
+++ b/storage/innobase/include/srv0start.h
@@ -33,10 +33,11 @@ Created 10/10/1995 Heikki Tuuri
struct dict_table_t;
/** Open the configured number of dedicated undo tablespaces.
-@param[in] create_new_db whether the database is being initialized
+@param[in] create_new_undo whether the undo tablespaces has to be created
+@param[in] mtr mini-transaction in case of reinitialize
+ of undo tablespaces
@return DB_SUCCESS or error code */
-dberr_t
-srv_undo_tablespaces_init(bool create_new_db);
+dberr_t srv_undo_tablespaces_init(bool create_new_undo, mtr_t *mtr= nullptr);
/** Start InnoDB.
@param[in] create_new_db whether to create a new database
diff --git a/storage/innobase/include/trx0rseg.h b/storage/innobase/include/trx0rseg.h
index 7ad20b0fff0..0b24a2c0335 100644
--- a/storage/innobase/include/trx0rseg.h
+++ b/storage/innobase/include/trx0rseg.h
@@ -306,7 +306,10 @@ which corresponds to the transaction just being committed.
In a replication slave, this updates the master binlog position
up to which replication has proceeded.
@param[in,out] rseg_header rollback segment header
-@param[in] trx committing transaction
+@param[in] log_file_name binlog file name
+@param[in] offset binlog offset value
@param[in,out] mtr mini-transaction */
-void trx_rseg_update_binlog_offset(buf_block_t *rseg_header, const trx_t *trx,
+void trx_rseg_update_binlog_offset(buf_block_t *rseg_header,
+ const char *log_file_name,
+ ulonglong log_offset,
mtr_t *mtr);
diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h
index 4d231077b12..ec3a58cbecd 100644
--- a/storage/innobase/include/trx0sys.h
+++ b/storage/innobase/include/trx0sys.h
@@ -855,6 +855,8 @@ class trx_sys_t
bool m_initialised;
+ /** True if there is no undo log to purge or rollback */
+ bool undo_log_empty= true;
public:
/** List of all transactions. */
thread_safe_trx_ilist_t trx_list;
@@ -1165,6 +1167,20 @@ public:
return count;
}
+ /** Set the undo log empty value */
+ void set_undo_empty(bool val)
+ {
+ if (undo_log_empty)
+ undo_log_empty= val;
+ }
+
+ /** Get the undo log empty value */
+ bool is_undo_empty() const { return undo_log_empty; }
+
+ /* Reset the trx_sys page and retain the dblwr information,
+ system rollback segment header page
+ @return error code */
+ inline dberr_t reset_page(mtr_t *mtr);
private:
static my_bool find_same_or_older_callback(rw_trx_hash_element_t *element,
trx_id_t *id)
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 8e291352d55..90d04ee5cd1 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -97,6 +97,7 @@ Created 2/16/1996 Heikki Tuuri
#include "btr0pcur.h"
#include "zlib.h"
#include "ut0crc32.h"
+#include "log.h"
/** We are prepared for a situation that we have this many threads waiting for
a transactional lock inside InnoDB. srv_start() sets the value. */
@@ -431,11 +432,239 @@ static dberr_t srv_undo_tablespace_create(const char* name)
return(err);
}
-/* Validate the number of undo opened undo tablespace and user given
-undo tablespace
+inline dberr_t trx_sys_t::reset_page(mtr_t *mtr)
+{
+ dberr_t err= DB_SUCCESS;
+ bool dblwr_enabled= true;
+ buf_block_t *sys_header= buf_page_get_gen(
+ page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO), 0, RW_X_LATCH, nullptr,
+ BUF_GET, mtr, &err);
+
+ if (err) return err;
+
+ dblwr_enabled=
+ mach_read_from_4(TRX_SYS_DOUBLEWRITE_MAGIC + TRX_SYS_DOUBLEWRITE +
+ sys_header->page.frame)
+ == TRX_SYS_DOUBLEWRITE_MAGIC_N;
+
+ char doublewrite[TRX_SYS_DOUBLEWRITE_BLOCK2 + 4];
+ memcpy(doublewrite, TRX_SYS_DOUBLEWRITE + sys_header->page.frame,
+ sizeof doublewrite);
+
+ fsp_init_file_page(fil_system.sys_space, sys_header, mtr);
+
+ mtr->write<2>(*sys_header, FIL_PAGE_TYPE + sys_header->page.frame,
+ FIL_PAGE_TYPE_TRX_SYS);
+
+ mtr->write<4>(*sys_header,
+ TRX_SYS + TRX_SYS_RSEGS + TRX_SYS_RSEG_PAGE_NO +
+ sys_header->page.frame, FSP_FIRST_RSEG_PAGE_NO);
+ mtr->memset(sys_header,
+ TRX_SYS + TRX_SYS_RSEGS + TRX_SYS_RSEG_SLOT_SIZE,
+ 254 * TRX_SYS_RSEG_SLOT_SIZE, 0xff);
+
+ static_assert(TRX_SYS_RSEG_SLOT_SIZE == 8, "");
+
+ if (dblwr_enabled)
+ {
+ mtr->memcpy(
+ *sys_header, sys_header->page.frame + TRX_SYS_DOUBLEWRITE,
+ doublewrite, sizeof doublewrite);
+ mtr->memmove(
+ *sys_header,
+ TRX_SYS_DOUBLEWRITE + FSEG_HEADER_SIZE + TRX_SYS_DOUBLEWRITE_REPEAT,
+ TRX_SYS_DOUBLEWRITE + FSEG_HEADER_SIZE, 12);
+ memcpy(
+ sys_header->page.frame + TRX_SYS_DOUBLEWRITE
+ + FSEG_HEADER_SIZE + TRX_SYS_DOUBLEWRITE_REPEAT,
+ sys_header->page.frame + TRX_SYS_DOUBLEWRITE + FSEG_HEADER_SIZE, 12);
+ }
+
+ trx_rseg_t *rseg= nullptr;
+ for (ulint rseg_id= 1; rseg_id < TRX_SYS_N_RSEGS; rseg_id++)
+ {
+ rseg= &trx_sys.rseg_array[rseg_id];
+ rseg->destroy();
+ rseg->init(nullptr, FIL_NULL);
+ }
+
+ return err;
+}
+
+/** Delete the old undo tablespaces present in the undo log directory */
+static dberr_t srv_undo_delete_old_tablespaces()
+{
+ if (recv_recovery_is_on())
+ mysql_mutex_lock(&log_sys.mutex);
+ /* Delete the old undo tablespaces*/
+ for (ulint i= 0; i < srv_undo_tablespaces_open; ++i)
+ fil_close_tablespace(srv_undo_space_id_start + i);
+
+ if (recv_recovery_is_on())
+ mysql_mutex_unlock(&log_sys.mutex);
+
+ DBUG_EXECUTE_IF("after_deleting_old_undo_abort", return DB_ERROR;);
+
+ /* Do checkpoint to get rid of old undo log tablespaces redo logs */
+ log_make_checkpoint();
+
+ DBUG_EXECUTE_IF("after_deleting_old_undo_success", return DB_ERROR;);
+
+ for (ulint i= 0; i < srv_undo_tablespaces_open; ++i)
+ {
+ char name[OS_FILE_MAX_PATH];
+ snprintf(name, sizeof name, "%s/undo%03zu", srv_undo_dir, i + 1);
+ os_file_delete_if_exists(innodb_data_file_key, name, nullptr);
+ }
+
+ return DB_SUCCESS;
+}
+
+/** Recreate the undo log tablespaces */
+static dberr_t srv_undo_tablespaces_reinit()
+{
+ mtr_t mtr;
+ dberr_t err;
+ buf_block_t *dict_hdr;
+
+ mtr.start();
+ if (srv_undo_tablespaces_open == 0)
+ {
+ /* Free the system rollback segment */
+ for (ulint i= 1; i < TRX_SYS_N_RSEGS; i++)
+ {
+ trx_rseg_t *rseg= &trx_sys.rseg_array[i];
+ if (!rseg->space)
+ continue;
+ buf_block_t *block= buf_page_get_gen(
+ rseg->page_id(), 0, RW_X_LATCH, nullptr, BUF_GET, &mtr, &err);
+ if (err) { mtr.commit(); return err; }
+ while (!fseg_free_step(TRX_RSEG + TRX_RSEG_FSEG_HEADER +
+ block->page.frame, &mtr));
+ }
+ }
+
+ /* Reset TRX_SYS page */
+ err= trx_sys.reset_page(&mtr);
+
+ if (trx_sys.recovered_binlog_lsn
+#ifdef WITH_WSREP
+ || trx_sys.recovered_wsrep_xid.is_null()
+#endif /* WITH_WSREP */
+ )
+ {
+ /* Update binlog offset, binlog file name & wsrep xid in
+ system tablespace rollback segment */
+ trx_rseg_t& rseg = trx_sys.rseg_array[0];
+ buf_block_t *rseg_hdr=
+ buf_page_get_gen(rseg.page_id(), 0, RW_X_LATCH, nullptr, BUF_GET,
+ &mtr, &err);
+ if (!rseg_hdr)
+ goto func_exit;
+
+ if (trx_sys.recovered_binlog_lsn > 0)
+ {
+ ut_d(const size_t len = strlen(trx_sys.recovered_binlog_filename) + 1);
+ ut_ad(len > 1);
+ ut_ad(len <= TRX_RSEG_BINLOG_NAME_LEN);
+ trx_rseg_update_binlog_offset(
+ rseg_hdr, trx_sys.recovered_binlog_filename,
+ trx_sys.recovered_binlog_offset, &mtr);
+ }
+
+#ifdef WITH_WSREP
+ if (!trx_sys.recovered_wsrep_xid.is_null())
+ trx_rseg_update_wsrep_checkpoint(
+ rseg_hdr, &trx_sys.recovered_wsrep_xid, &mtr);
+#endif /* WITH_WSREP */
+ }
+
+ mtr.commit();
+
+ DBUG_EXECUTE_IF("after_rseg_reset_abort",
+ log_write_up_to(mtr.commit_lsn(), true);
+ err= DB_ERROR;);
+
+ if (err) return err;
+
+ sql_print_information(
+ "InnoDB: Reinitializing innodb_undo_tablespaces= %u from %u",
+ srv_undo_tablespaces, srv_undo_tablespaces_open);
+
+ /* Delete the old undo tablespaces */
+ err= srv_undo_delete_old_tablespaces();
+ if (err) return err;
+
+ mtr.start();
+
+ dict_hdr= buf_page_get_gen(
+ page_id_t(DICT_HDR_SPACE, DICT_HDR_PAGE_NO), 0, RW_X_LATCH,
+ nullptr, BUF_GET, &mtr, &err);
+
+ if (!dict_hdr)
+ goto func_exit;
+
+ if (srv_undo_tablespaces == 0)
+ {
+ srv_undo_space_id_start= 0;
+ srv_undo_tablespaces_open= 0;
+ goto func_exit;
+ }
+
+ /* Assign the new space id for the first undo tablespace */
+ srv_undo_space_id_start = mach_read_from_4(
+ DICT_HDR + DICT_HDR_MAX_SPACE_ID + dict_hdr->page.frame);
+
+ if (srv_undo_space_id_start + srv_undo_tablespaces
+ > SRV_SPACE_ID_UPPER_BOUND)
+ {
+ err= DB_ERROR;
+ sql_print_error("InnoDB: Running out of tablespace id");
+ goto func_exit;
+ }
+
+ if (fil_assign_new_space_id(&srv_undo_space_id_start))
+ mtr.write<4>(*dict_hdr, DICT_HDR + DICT_HDR_MAX_SPACE_ID
+ + dict_hdr->page.frame, srv_undo_space_id_start);
+
+ /* Re-create the new undo tablespaces */
+ err= srv_undo_tablespaces_init(true, &mtr);
+func_exit:
+ mtr.commit();
+
+ DBUG_EXECUTE_IF("after_reinit_undo_abort",
+ log_write_up_to(mtr.commit_lsn(), true);
+ err= DB_ERROR;);
+ if (err) return err;
+
+ /* Usually, recovery must work no matter when
+ log_checkpoints are triggered. This is a special case,
+ because this code is executed as part of InnoDB startup.
+ Backup requires that the server has been started up,
+ backup should never observe the log records that
+ were written in mtr and also srv_undo_tablespaces_init()
+ initializes the undo tablespace start id based on page0
+ content before reading the redo log */
+ log_make_checkpoint();
+
+ DBUG_EXECUTE_IF("after_reinit_undo_success", err= DB_ERROR;);
+ srv_undo_tablespaces_active= srv_undo_tablespaces;
+ return err;
+}
+
+/* Reinitialize the undo tablespaces when there is no undo log
+left to purge/rollback and validate the number of undo opened
+undo tablespace and user given undo tablespace
@return DB_SUCCESS if it is valid */
-static dberr_t srv_validate_undo_tablespaces()
+static dberr_t srv_undo_tablespaces_reinitialize()
{
+
+ /* Re-create the undo tablespaces if it has no undo logs
+ left to purge/rollback */
+ if (srv_undo_tablespaces != srv_undo_tablespaces_open
+ && trx_sys.is_undo_empty())
+ return srv_undo_tablespaces_reinit();
+
/* If the user says that there are fewer than what we find we
tolerate that discrepancy but not the inverse. Because there could
be unused undo tablespaces for future use. */
@@ -449,15 +678,13 @@ static dberr_t srv_validate_undo_tablespaces()
return DB_ERROR;
}
+ else if (srv_undo_tablespaces < srv_undo_tablespaces_open)
+ sql_print_warning("InnoDB: Cannot change innodb_undo_tablespaces=%u "
+ "because previous shutdown was not with "
+ "innodb_fast_shutdown=0", srv_undo_tablespaces);
else if (srv_undo_tablespaces_open > 0)
- {
ib::info() << "Opened " << srv_undo_tablespaces_open
<< " undo tablespaces";
-
- if (srv_undo_tablespaces == 0)
- ib::warn() << "innodb_undo_tablespaces=0 disables"
- " dedicated undo log tablespaces";
- }
return DB_SUCCESS;
}
@@ -643,23 +870,23 @@ srv_check_undo_redo_logs_exists()
return(DB_SUCCESS);
}
-static dberr_t srv_all_undo_tablespaces_open(bool create_new_db, ulint n_undo)
+static dberr_t srv_all_undo_tablespaces_open(bool create_new_undo, ulint n_undo)
{
/* Open all the undo tablespaces that are currently in use. If we
fail to open any of these it is a fatal error. The tablespace ids
should be contiguous. It is a fatal error because they are required
for recovery and are referenced by the UNDO logs (a.k.a RBS). */
- ulint prev_id= create_new_db ? srv_undo_space_id_start - 1 : 0;
+ ulint prev_id= create_new_undo ? srv_undo_space_id_start - 1 : 0;
for (ulint i= 0; i < n_undo; ++i)
{
char name[OS_FILE_MAX_PATH];
snprintf(name, sizeof name, "%s/undo%03zu", srv_undo_dir, i + 1);
- ulint space_id= srv_undo_tablespace_open(create_new_db, name, i);
+ ulint space_id= srv_undo_tablespace_open(create_new_undo, name, i);
if (!space_id)
{
- if (!create_new_db)
+ if (!create_new_undo)
break;
ib::error() << "Unable to open create tablespace '" << name << "'.";
return DB_ERROR;
@@ -686,24 +913,25 @@ static dberr_t srv_all_undo_tablespaces_open(bool create_new_db, ulint n_undo)
{
char name[OS_FILE_MAX_PATH];
snprintf(name, sizeof name, "%s/undo%03zu", srv_undo_dir, i);
- if (!srv_undo_tablespace_open(create_new_db, name, i))
+ if (!srv_undo_tablespace_open(create_new_undo, name, i))
break;
++srv_undo_tablespaces_open;
}
- return srv_validate_undo_tablespaces();
+ return DB_SUCCESS;
}
/** Open the configured number of dedicated undo tablespaces.
-@param[in] create_new_db whether the database is being initialized
+@param[in] create_new_undo whether the undo tablespaces has to be created
+@param[in] mtr mini-transaction in case of reinitialize
+ of undo tablespaces
@return DB_SUCCESS or error code */
-dberr_t
-srv_undo_tablespaces_init(bool create_new_db)
+dberr_t srv_undo_tablespaces_init(bool create_new_undo, mtr_t *mtr)
{
srv_undo_tablespaces_open= 0;
ut_a(srv_undo_tablespaces <= TRX_SYS_N_RSEGS);
- ut_a(!create_new_db || srv_operation == SRV_OPERATION_NORMAL);
+ ut_a(!create_new_undo || srv_operation == SRV_OPERATION_NORMAL);
if (srv_undo_tablespaces == 1)
srv_undo_tablespaces= 0;
@@ -711,9 +939,8 @@ srv_undo_tablespaces_init(bool create_new_db)
/* Create the undo spaces only if we are creating a new
instance. We don't allow creating of new undo tablespaces
in an existing instance (yet). */
- if (create_new_db)
+ if (create_new_undo)
{
- srv_undo_space_id_start= 1;
DBUG_EXECUTE_IF("innodb_undo_upgrade", srv_undo_space_id_start= 3;);
for (ulint i= 0; i < srv_undo_tablespaces; ++i)
@@ -734,11 +961,11 @@ srv_undo_tablespaces_init(bool create_new_db)
already exist. */
srv_undo_tablespaces_active= srv_undo_tablespaces;
- ulint n_undo= (create_new_db || srv_operation == SRV_OPERATION_BACKUP ||
+ ulint n_undo= (create_new_undo || srv_operation == SRV_OPERATION_BACKUP ||
srv_operation == SRV_OPERATION_RESTORE_DELTA)
? srv_undo_tablespaces : TRX_SYS_N_RSEGS;
- if (dberr_t err= srv_all_undo_tablespaces_open(create_new_db, n_undo))
+ if (dberr_t err= srv_all_undo_tablespaces_open(create_new_undo, n_undo))
return err;
/* Initialize srv_undo_space_id_start=0 when there are no
@@ -746,18 +973,21 @@ srv_undo_tablespaces_init(bool create_new_db)
if (srv_undo_tablespaces_open == 0)
srv_undo_space_id_start= 0;
- if (create_new_db)
+ if (create_new_undo || mtr)
{
- mtr_t mtr;
+ mtr_t *create_mtr= mtr;
+ if (!create_mtr) create_mtr= new mtr_t();
for (ulint i= 0; i < srv_undo_tablespaces; ++i)
{
- mtr.start();
+ if (!mtr) create_mtr->start();
dberr_t err= fsp_header_init(fil_space_get(srv_undo_space_id_start + i),
- SRV_UNDO_TABLESPACE_SIZE_IN_PAGES, &mtr);
- mtr.commit();
- if (err)
- return err;
+ SRV_UNDO_TABLESPACE_SIZE_IN_PAGES,
+ create_mtr);
+ if (!mtr) create_mtr->commit();
+ if (err) return err;
}
+
+ if (!mtr) delete create_mtr;
}
return DB_SUCCESS;
@@ -1309,6 +1539,8 @@ dberr_t srv_start(bool create_new_db)
}
return(srv_init_abort(err));
}
+
+ srv_undo_space_id_start= 1;
} else {
srv_log_file_size = 0;
@@ -1475,10 +1707,7 @@ file_checked:
/* This must precede recv_sys.apply(true). */
srv_undo_tablespaces_active
= trx_rseg_get_n_undo_tablespaces();
- err = srv_validate_undo_tablespaces();
- if (err != DB_SUCCESS) {
- return srv_init_abort(err);
- }
+
if (srv_operation != SRV_OPERATION_RESTORE) {
dict_sys.load_sys_tables();
}
@@ -1512,11 +1741,18 @@ file_checked:
}
}
+ err= srv_undo_tablespaces_reinitialize();
+ if (err) return srv_init_abort(err);
+
+ if (srv_undo_tablespaces != srv_undo_tablespaces_open)
+ srv_undo_tablespaces= (ulong) srv_undo_tablespaces_open;
+
fil_system.space_id_reuse_warned = false;
if (!srv_read_only_mode) {
const ulint flags = FSP_FLAGS_PAGE_SSIZE();
- for (ulint id = 0; id <= srv_undo_tablespaces; id++) {
+ for (ulint id = srv_undo_space_id_start;
+ id <= srv_undo_tablespaces; id++) {
if (fil_space_t* space = fil_space_get(id)) {
fsp_flags_try_adjust(space, flags);
}
diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc
index b5d00d9624f..f7b77260a4c 100644
--- a/storage/innobase/trx/trx0purge.cc
+++ b/storage/innobase/trx/trx0purge.cc
@@ -306,7 +306,9 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
/* Update the latest MySQL binlog name and offset info
in rollback segment header if MySQL binlogging is on
or the database server is a MySQL replication save. */
- trx_rseg_update_binlog_offset(rseg_header, trx, mtr);
+ trx_rseg_update_binlog_offset(
+ rseg_header, trx->mysql_log_file_name,
+ trx->mysql_log_offset, mtr);
}
/* Add the log as the first in the history list */
diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc
index 760c4e707ce..fbe2bdb36d6 100644
--- a/storage/innobase/trx/trx0rseg.cc
+++ b/storage/innobase/trx/trx0rseg.cc
@@ -30,6 +30,7 @@ Created 3/26/1996 Heikki Tuuri
#include "srv0srv.h"
#include "trx0purge.h"
#include "srv0mon.h"
+#include "log.h"
#ifdef WITH_WSREP
# include <mysql/service_wsrep.h>
@@ -369,7 +370,6 @@ void trx_rseg_t::destroy()
void trx_rseg_t::init(fil_space_t *space, uint32_t page)
{
latch.SRW_LOCK_INIT(trx_rseg_latch_key);
- ut_ad(!this->space);
this->space= space;
page_no= page;
last_page_no= FIL_NULL;
@@ -414,6 +414,7 @@ static dberr_t trx_undo_lists_init(trx_rseg_t *rseg, trx_id_t &max_trx_id,
const buf_block_t *rseg_header)
{
ut_ad(srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN);
+ bool is_undo_empty= true;
for (ulint i= 0; i < TRX_RSEG_N_SLOTS; i++)
{
@@ -424,11 +425,14 @@ static dberr_t trx_undo_lists_init(trx_rseg_t *rseg, trx_id_t &max_trx_id,
max_trx_id);
if (!undo)
return DB_CORRUPTION;
+ if (is_undo_empty)
+ is_undo_empty= !undo->size || undo->state == TRX_UNDO_CACHED;
rseg->curr_size+= undo->size;
MONITOR_INC(MONITOR_NUM_UNDO_SLOT_USED);
}
}
+ trx_sys.set_undo_empty(is_undo_empty);
return DB_SUCCESS;
}
@@ -532,6 +536,7 @@ static dberr_t trx_rseg_mem_restore(trx_rseg_t *rseg, trx_id_t &max_trx_id,
purge_sys.purge_queue.push(*rseg);
}
+ trx_sys.set_undo_empty(rseg->history_size == 0);
return err;
}
@@ -592,10 +597,24 @@ dberr_t trx_rseg_array_init()
sys, rseg_id);
if (page_no != FIL_NULL) {
trx_rseg_t& rseg = trx_sys.rseg_array[rseg_id];
- rseg.init(fil_space_get(
- trx_sysf_rseg_get_space(
- sys, rseg_id)),
- page_no);
+ uint32_t space_id=
+ trx_sysf_rseg_get_space(
+ sys, rseg_id);
+
+ fil_space_t *rseg_space =
+ fil_space_get(space_id);
+ if (!rseg_space) {
+ mtr_commit(&mtr);
+ err = DB_ERROR;
+ sql_print_error(
+ "Failed to open the undo "
+ "tablespace undo%03zu",
+ (space_id -
+ srv_undo_space_id_start + 1));
+ break;
+ }
+
+ rseg.init(rseg_space, page_no);
ut_ad(rseg.is_persistent());
if ((err = trx_rseg_mem_restore(
&rseg, max_trx_id, &mtr))
@@ -685,29 +704,28 @@ which corresponds to the transaction just being committed.
In a replication slave, this updates the master binlog position
up to which replication has proceeded.
@param[in,out] rseg_header rollback segment header
-@param[in] trx committing transaction
+@param[in] log_file_name binlog file name
+@param[in] log_offset binlog file offset
@param[in,out] mtr mini-transaction */
-void trx_rseg_update_binlog_offset(buf_block_t *rseg_header, const trx_t *trx,
+void trx_rseg_update_binlog_offset(buf_block_t *rseg_header,
+ const char *log_file_name,
+ ulonglong log_offset,
mtr_t *mtr)
{
- DBUG_LOG("trx", "trx_mysql_binlog_offset: " << trx->mysql_log_offset);
-
- const size_t len = strlen(trx->mysql_log_file_name) + 1;
+ DBUG_PRINT("trx", ("trx_mysql_binlog_offset %llu", log_offset));
+ const size_t len= strlen(log_file_name) + 1;
+ ut_ad(len > 1);
- ut_ad(len > 1);
+ if (UNIV_UNLIKELY(len > TRX_RSEG_BINLOG_NAME_LEN))
+ return;
- if (UNIV_UNLIKELY(len > TRX_RSEG_BINLOG_NAME_LEN)) {
- return;
- }
-
- mtr->write<8,mtr_t::MAYBE_NOP>(*rseg_header,
- TRX_RSEG + TRX_RSEG_BINLOG_OFFSET
- + rseg_header->page.frame,
- trx->mysql_log_offset);
+ mtr->write<8,mtr_t::MAYBE_NOP>(
+ *rseg_header,
+ TRX_RSEG + TRX_RSEG_BINLOG_OFFSET + rseg_header->page.frame,
+ log_offset);
- void* name = TRX_RSEG + TRX_RSEG_BINLOG_NAME + rseg_header->page.frame;
+ byte *name= TRX_RSEG + TRX_RSEG_BINLOG_NAME + rseg_header->page.frame;
- if (memcmp(trx->mysql_log_file_name, name, len)) {
- mtr->memcpy(*rseg_header, name, trx->mysql_log_file_name, len);
- }
+ if (memcmp(log_file_name, name, len))
+ mtr->memcpy(*rseg_header, name, log_file_name, len);
}
diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc
index 2479e5a4cc1..e98dcef0250 100644
--- a/storage/innobase/trx/trx0sys.cc
+++ b/storage/innobase/trx/trx0sys.cc
@@ -325,10 +325,9 @@ bool trx_sys_create_rsegs()
/* Increase the number of active undo
tablespace in case new rollback segment
assigned to new undo tablespace. */
- if (space > srv_undo_tablespaces_active) {
+ if (space > (srv_undo_space_id_start
+ + srv_undo_tablespaces_active - 1)) {
srv_undo_tablespaces_active++;
-
- ut_ad(srv_undo_tablespaces_active == space);
}
}
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index 111f8fe5f3a..51f333532a5 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -725,6 +725,12 @@ corrupted:
return err;
}
+ if (trx_sys.is_undo_empty()) {
+func_exit:
+ purge_sys.clone_oldest_view();
+ return DB_SUCCESS;
+ }
+
/* Look from the rollback segments if there exist undo logs for
transactions. */
const time_t start_time = time(NULL);
@@ -785,8 +791,7 @@ corrupted:
ib::info() << "Trx id counter is " << trx_sys.get_max_trx_id();
}
- purge_sys.clone_oldest_view();
- return DB_SUCCESS;
+ goto func_exit;
}
/** Assign a persistent rollback segment in a round-robin fashion,
@@ -843,8 +848,7 @@ static trx_rseg_t* trx_assign_rseg_low()
ut_ad(rseg->is_persistent());
if (rseg->space != fil_system.sys_space) {
- if (rseg->skip_allocation()
- || !srv_undo_tablespaces) {
+ if (rseg->skip_allocation()) {
continue;
}
} else if (const fil_space_t *space =