mirror of
https://github.com/MariaDB/server.git
synced 2025-11-30 05:23:50 +03:00
MDEV-12289 Keep 128 persistent rollback segments for compatibility and performance
InnoDB divides the allocation of undo logs into rollback segments. The DB_ROLL_PTR system column of clustered indexes can address up to 128 rollback segments (TRX_SYS_N_RSEGS). Originally, InnoDB only created one rollback segment. In MySQL 5.5 or in the InnoDB Plugin for MySQL 5.1, all 128 rollback segments were created. MySQL 5.7 hard-codes the rollback segment IDs 1..32 for temporary undo logs. On upgrade, unless a slow shutdown (innodb_fast_shutdown=0) was performed on the old server instance, these rollback segments could be in use by transactions that are in XA PREPARE state or transactions that were left behind by a server kill followed by a normal shutdown immediately after restart. Persistent tables cannot refer to temporary undo logs or vice versa. Therefore, we should keep two distinct sets of rollback segments: one for persistent tables and another for temporary tables. In this way, all 128 rollback segments will be available for both types of tables, which could improve performance. Also, MariaDB 10.2 will remain more compatible than MySQL 5.7 with data files from earlier versions of MySQL or MariaDB. trx_sys_t::temp_rsegs[TRX_SYS_N_RSEGS]: A new array of temporary rollback segments. The trx_sys_t::rseg_array[TRX_SYS_N_RSEGS] will be solely for persistent undo logs. srv_tmp_undo_logs. Remove. Use the constant TRX_SYS_N_RSEGS. srv_available_undo_logs: Change the type to ulong. trx_rseg_get_on_id(): Remove. Instead, let the callers refer to trx_sys directly. trx_rseg_create(), trx_sysf_rseg_find_free(): Remove unneeded parameters. These functions only deal with persistent undo logs. trx_temp_rseg_create(): New function, to create all temporary rollback segments at server startup. trx_rseg_t::is_persistent(): Determine if the rollback segment is for persistent tables. trx_sys_is_noredo_rseg_slot(): Remove. The callers must know based on context (such as table handle) whether the DB_ROLL_PTR is referring to a persistent undo log. trx_sys_create_rsegs(): Remove all parameters, which were always passed as global variables. Instead, modify the global variables directly. enum trx_rseg_type_t: Remove. trx_t::get_temp_rseg(): A method to ensure that a temporary rollback segment has been assigned for the transaction. trx_t::assign_temp_rseg(): Replaces trx_assign_rseg(). trx_purge_free_segment(), trx_purge_truncate_rseg_history(): Remove the redundant variable noredo=false. Temporary undo logs are discarded immediately at transaction commit or rollback, not lazily by purge. trx_purge_mark_undo_for_truncate(): Remove references to the temporary rollback segments. trx_purge_mark_undo_for_truncate(): Remove a check for temporary rollback segments. Only the dedicated persistent undo log tablespaces can be truncated. trx_undo_get_undo_rec_low(), trx_undo_get_undo_rec(): Add the parameter is_temp. trx_rseg_mem_restore(): Split from trx_rseg_mem_create(). Initialize the undo log and the rollback segment from the file data structures. trx_sysf_get_n_rseg_slots(): Renamed from trx_sysf_used_slots_for_redo_rseg(). Count the persistent rollback segment headers that have been initialized. trx_sys_close(): Also free trx_sys->temp_rsegs[]. get_next_redo_rseg(): Merged to trx_assign_rseg_low(). trx_assign_rseg_low(): Remove the parameters and access the global variables directly. Revert to simple round-robin, now that the whole trx_sys->rseg_array[] is for persistent undo log again. get_next_noredo_rseg(): Moved to trx_t::assign_temp_rseg(). srv_undo_tablespaces_init(): Remove some parameters and use the global variables directly. Clarify some error messages. Adjust the test innodb.log_file. Apparently, before these changes, InnoDB somehow ignored missing dedicated undo tablespace files that are pointed by the TRX_SYS header page, possibly losing part of essential transaction system state.
This commit is contained in:
@@ -804,20 +804,12 @@ srv_check_undo_redo_logs_exists()
|
||||
|
||||
undo::undo_spaces_t undo::Truncate::s_fix_up_spaces;
|
||||
|
||||
/********************************************************************
|
||||
Opens the configured number of undo tablespaces.
|
||||
/** Open the configured number of dedicated undo tablespaces.
|
||||
@param[in] create_new_db whether the database is being initialized
|
||||
@return DB_SUCCESS or error code */
|
||||
static
|
||||
dberr_t
|
||||
srv_undo_tablespaces_init(
|
||||
/*======================*/
|
||||
bool create_new_db, /*!< in: TRUE if new db being
|
||||
created */
|
||||
const ulint n_conf_tablespaces, /*!< in: configured undo
|
||||
tablespaces */
|
||||
ulint* n_opened) /*!< out: number of UNDO
|
||||
tablespaces successfully
|
||||
discovered and opened */
|
||||
srv_undo_tablespaces_init(bool create_new_db)
|
||||
{
|
||||
ulint i;
|
||||
dberr_t err = DB_SUCCESS;
|
||||
@@ -825,9 +817,9 @@ srv_undo_tablespaces_init(
|
||||
ulint n_undo_tablespaces;
|
||||
ulint undo_tablespace_ids[TRX_SYS_N_RSEGS + 1];
|
||||
|
||||
*n_opened = 0;
|
||||
srv_undo_tablespaces_open = 0;
|
||||
|
||||
ut_a(n_conf_tablespaces <= TRX_SYS_N_RSEGS);
|
||||
ut_a(srv_undo_tablespaces <= TRX_SYS_N_RSEGS);
|
||||
|
||||
memset(undo_tablespace_ids, 0x0, sizeof(undo_tablespace_ids));
|
||||
|
||||
@@ -839,7 +831,7 @@ srv_undo_tablespaces_init(
|
||||
the location of the undo tablespaces and their space ids this
|
||||
restriction will/should be lifted. */
|
||||
|
||||
for (i = 0; create_new_db && i < n_conf_tablespaces; ++i) {
|
||||
for (i = 0; create_new_db && i < srv_undo_tablespaces; ++i) {
|
||||
char name[OS_FILE_MAX_PATH];
|
||||
|
||||
ut_snprintf(
|
||||
@@ -902,7 +894,7 @@ srv_undo_tablespaces_init(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
n_undo_tablespaces = n_conf_tablespaces;
|
||||
n_undo_tablespaces = srv_undo_tablespaces;
|
||||
|
||||
for (i = 1; i <= n_undo_tablespaces; ++i) {
|
||||
undo_tablespace_ids[i - 1] = i;
|
||||
@@ -944,7 +936,7 @@ srv_undo_tablespaces_init(
|
||||
|
||||
prev_space_id = undo_tablespace_ids[i];
|
||||
|
||||
++*n_opened;
|
||||
++srv_undo_tablespaces_open;
|
||||
}
|
||||
|
||||
/* Open any extra unused undo tablespaces. These must be contiguous.
|
||||
@@ -968,19 +960,17 @@ srv_undo_tablespaces_init(
|
||||
|
||||
++n_undo_tablespaces;
|
||||
|
||||
++*n_opened;
|
||||
++srv_undo_tablespaces_open;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
if (n_conf_tablespaces > n_undo_tablespaces) {
|
||||
ib::error() << "Expected to open " << n_conf_tablespaces
|
||||
<< " undo tablespaces but was able to find only "
|
||||
<< n_undo_tablespaces << " undo tablespaces. Set the"
|
||||
" innodb_undo_tablespaces parameter to the correct"
|
||||
" value and retry. Suggested value is "
|
||||
if (srv_undo_tablespaces > n_undo_tablespaces) {
|
||||
ib::error() << "Expected to open innodb_undo_tablespaces="
|
||||
<< srv_undo_tablespaces
|
||||
<< " but was able to find only "
|
||||
<< n_undo_tablespaces;
|
||||
|
||||
return(err != DB_SUCCESS ? err : DB_ERROR);
|
||||
@@ -988,15 +978,13 @@ srv_undo_tablespaces_init(
|
||||
} else if (n_undo_tablespaces > 0) {
|
||||
|
||||
ib::info() << "Opened " << n_undo_tablespaces
|
||||
<< " undo tablespaces";
|
||||
<< " undo tablespaces ("
|
||||
<< srv_undo_tablespaces_active
|
||||
<< " active)";
|
||||
|
||||
ib::info() << srv_undo_tablespaces_active << " undo tablespaces"
|
||||
<< " made active";
|
||||
|
||||
if (n_conf_tablespaces == 0) {
|
||||
ib::warn() << "Will use system tablespace for all newly"
|
||||
<< " created rollback-segment as"
|
||||
<< " innodb_undo_tablespaces=0";
|
||||
if (srv_undo_tablespaces == 0) {
|
||||
ib::warn() << "innodb_undo_tablespaces=0 disables"
|
||||
" dedicated undo log tablespaces";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2087,10 +2075,7 @@ files_checked:
|
||||
fil_open_log_and_system_tablespace_files();
|
||||
ut_d(fil_space_get(0)->recv_size = srv_sys_space_size_debug);
|
||||
|
||||
err = srv_undo_tablespaces_init(
|
||||
create_new_db,
|
||||
srv_undo_tablespaces,
|
||||
&srv_undo_tablespaces_open);
|
||||
err = srv_undo_tablespaces_init(create_new_db);
|
||||
|
||||
/* If the force recovery is set very high then we carry on regardless
|
||||
of all errors. Basically this is fingers crossed mode. */
|
||||
@@ -2512,22 +2497,7 @@ files_checked:
|
||||
ut_a(srv_undo_logs > 0);
|
||||
ut_a(srv_undo_logs <= TRX_SYS_N_RSEGS);
|
||||
|
||||
/* The number of rsegs that exist in InnoDB is given by status
|
||||
variable srv_available_undo_logs. The number of rsegs to use can
|
||||
be set using the dynamic global variable srv_undo_logs. */
|
||||
|
||||
srv_available_undo_logs = trx_sys_create_rsegs(
|
||||
srv_undo_tablespaces, srv_undo_logs, srv_tmp_undo_logs);
|
||||
|
||||
if (srv_available_undo_logs == ULINT_UNDEFINED) {
|
||||
/* Can only happen if server is read only. */
|
||||
ut_a(srv_read_only_mode);
|
||||
srv_undo_logs = ULONG_UNDEFINED;
|
||||
} else if (srv_available_undo_logs < srv_undo_logs
|
||||
&& !srv_force_recovery && !recv_needed_recovery) {
|
||||
ib::error() << "System or UNDO tablespace is running of out"
|
||||
<< " of space";
|
||||
/* Should due to out of file space. */
|
||||
if (!trx_sys_create_rsegs()) {
|
||||
return(srv_init_abort(DB_ERROR));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user