1
0
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:
Marko Mäkelä
2017-03-30 13:11:34 +03:00
parent 0b9a13a8fc
commit 124bae082b
18 changed files with 365 additions and 621 deletions

View File

@@ -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));
}