[Commits] 6150002055f: MDEV-12289 Keep 128 persistent rollback segments for compatibility and performance

marko.makela at mariadb.com marko.makela at mariadb.com
Thu Mar 30 14:37:45 EEST 2017


revision-id: 6150002055f5d8a2ed7a905e9bf2b184cadfccbc (mariadb-10.2.4-109-g6150002055f)
parent(s): a0c79bcf0062adc2489f0b0bed98b05d4db8f476
author: Marko Mäkelä
committer: Marko Mäkelä
timestamp: 2017-03-30 14:37:45 +0300
message:

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[].

trx_assign_rseg_low(), get_next_redo_rseg(): Remove the parameters
and use 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.

---
 mysql-test/suite/innodb/r/log_file.result |   4 +-
 mysql-test/suite/innodb/t/log_file.test   |   6 +-
 storage/innobase/handler/ha_innodb.cc     |   2 +-
 storage/innobase/include/srv0srv.h        |   6 +-
 storage/innobase/include/trx0rseg.h       |  32 ++---
 storage/innobase/include/trx0sys.h        |  39 ++----
 storage/innobase/include/trx0sys.ic       |  12 --
 storage/innobase/include/trx0trx.h        |  30 ++--
 storage/innobase/row/row0purge.cc         |   5 +-
 storage/innobase/srv/srv0srv.cc           |  53 ++++---
 storage/innobase/srv/srv0start.cc         |  72 +++-------
 storage/innobase/trx/trx0purge.cc         |  51 ++-----
 storage/innobase/trx/trx0rec.cc           |  47 +++----
 storage/innobase/trx/trx0rseg.cc          | 144 ++++++++++---------
 storage/innobase/trx/trx0sys.cc           | 220 ++++++++++--------------------
 storage/innobase/trx/trx0trx.cc           | 214 ++++++++---------------------
 storage/innobase/trx/trx0undo.cc          |   6 +-
 17 files changed, 344 insertions(+), 599 deletions(-)

diff --git a/mysql-test/suite/innodb/r/log_file.result b/mysql-test/suite/innodb/r/log_file.result
index 352e4b76cf1..918faec8ada 100644
--- a/mysql-test/suite/innodb/r/log_file.result
+++ b/mysql-test/suite/innodb/r/log_file.result
@@ -207,7 +207,7 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES
 WHERE engine = 'innodb'
 AND support IN ('YES', 'DEFAULT', 'ENABLED');
 ENGINE	SUPPORT	COMMENT	TRANSACTIONS	XA	SAVEPOINTS
-FOUND /Expected to open 3 undo tablespaces but was able to find only 1 undo tablespaces/ in mysqld.1.err
+FOUND /InnoDB: Unable to open undo tablespace.*undo002/ in mysqld.1.err
 bak_ib_logfile0
 bak_ib_logfile1
 bak_ib_logfile2
@@ -244,7 +244,7 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES
 WHERE engine = 'innodb'
 AND support IN ('YES', 'DEFAULT', 'ENABLED');
 ENGINE	SUPPORT	COMMENT	TRANSACTIONS	XA	SAVEPOINTS
-FOUND /Expected to open 3 undo tablespaces but was able to find only 0 undo tablespaces/ in mysqld.1.err
+FOUND /InnoDB: Unable to open undo tablespace.*undo001/ in mysqld.1.err
 bak_ib_logfile0
 bak_ib_logfile1
 bak_ib_logfile2
diff --git a/mysql-test/suite/innodb/t/log_file.test b/mysql-test/suite/innodb/t/log_file.test
index c50257a69be..e0f4b85c682 100644
--- a/mysql-test/suite/innodb/t/log_file.test
+++ b/mysql-test/suite/innodb/t/log_file.test
@@ -41,7 +41,7 @@ AND support IN ('YES', 'DEFAULT', 'ENABLED');
 --let $ibp=$ibp --innodb-data-file-path=ibdata1:16M;ibdata2:10M:autoextend
 
 --echo # Start mysqld without the possibility to create innodb_undo_tablespaces
---let $restart_parameters= $ibp --innodb-undo-tablespaces=3
+--let $restart_parameters= $ibp
 --mkdir $bugdir/undo002
 --source include/restart_mysqld.inc
 eval $check_no_innodb;
@@ -172,7 +172,7 @@ let SEARCH_PATTERN=undo tablespace .*undo003.* exists\. Creating system tablespa
 --source include/start_mysqld.inc
 eval $check_no_innodb;
 --source include/shutdown_mysqld.inc
-let SEARCH_PATTERN=Expected to open 3 undo tablespaces but was able to find only 1 undo tablespaces;
+let SEARCH_PATTERN=InnoDB: Unable to open undo tablespace.*undo002;
 --source include/search_pattern_in_file.inc
 # clean up & Restore
 --source ../include/log_file_cleanup.inc
@@ -184,7 +184,7 @@ let SEARCH_PATTERN=Expected to open 3 undo tablespaces but was able to find only
 --source include/start_mysqld.inc
 eval $check_no_innodb;
 --source include/shutdown_mysqld.inc
-let SEARCH_PATTERN=Expected to open 3 undo tablespaces but was able to find only 0 undo tablespaces;
+let SEARCH_PATTERN=InnoDB: Unable to open undo tablespace.*undo001;
 --source include/search_pattern_in_file.inc
 
 # clean up & Restore
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 3dc22fe58d8..6aacdd48ad8 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -22140,7 +22140,7 @@ innobase_undo_logs_init_default_max()
 {
 	MYSQL_SYSVAR_NAME(undo_logs).max_val
 		= MYSQL_SYSVAR_NAME(undo_logs).def_val
-		= static_cast<unsigned long>(srv_available_undo_logs);
+		= srv_available_undo_logs;
 }
 
 /****************************************************************************
diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h
index e469cd90737..eb08c478965 100644
--- a/storage/innobase/include/srv0srv.h
+++ b/storage/innobase/include/srv0srv.h
@@ -334,9 +334,6 @@ extern my_bool	srv_undo_log_truncate;
 /* Enables or disables this prefix optimization.  Disabled by default. */
 extern my_bool	srv_prefix_index_cluster_optimization;
 
-/** UNDO logs not redo logged, these logs reside in the temp tablespace.*/
-extern const ulong	srv_tmp_undo_logs;
-
 /** Default size of UNDO tablespace while it is created new. */
 extern const ulint	SRV_UNDO_TABLESPACE_SIZE_IN_PAGES;
 
@@ -518,7 +515,8 @@ extern uint	srv_spin_wait_delay;
 extern ibool	srv_priority_boost;
 
 extern ulint	srv_truncated_status_writes;
-extern ulint	srv_available_undo_logs;
+/** Number of initialized rollback segments for persistent undo log */
+extern ulong	srv_available_undo_logs;
 
 #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
 extern my_bool	srv_ibuf_disable_background_merge;
diff --git a/storage/innobase/include/trx0rseg.h b/storage/innobase/include/trx0rseg.h
index e17d11b383e..95774cbf476 100644
--- a/storage/innobase/include/trx0rseg.h
+++ b/storage/innobase/include/trx0rseg.h
@@ -85,16 +85,6 @@ trx_rsegf_undo_find_free(
 /*=====================*/
 	trx_rsegf_t*	rsegf,	/*!< in: rollback segment header */
 	mtr_t*		mtr);	/*!< in: mtr */
-/** Get a rollback segment.
- at param[in]	id	rollback segment id
- at return rollback segment */
-UNIV_INLINE
-trx_rseg_t*
-trx_rseg_get_on_id(ulint id)
-{
-	ut_a(id < TRX_SYS_N_RSEGS);
-	return(trx_sys->rseg_array[id]);
-}
 
 /** Creates a rollback segment header.
 This function is called only when a new rollback segment is created in
@@ -119,14 +109,14 @@ trx_rseg_array_init();
 void
 trx_rseg_mem_free(trx_rseg_t* rseg);
 
-/*********************************************************************
-Creates a rollback segment. */
+/** Create a persistent rollback segment.
+ at param[in]	space_id	system or undo tablespace id */
 trx_rseg_t*
-trx_rseg_create(
-/*============*/
-	ulint	space_id,	/*!< in: id of UNDO tablespace */
-	ulint   nth_free_slot);	/*!< in: allocate nth free slot.
-				0 means next free slots. */
+trx_rseg_create(ulint space_id);
+
+/** Create the temporary rollback segments. */
+void
+trx_temp_rseg_create();
 
 /********************************************************************
 Get the number of unique rollback tablespaces in use except space id 0.
@@ -205,6 +195,14 @@ struct trx_rseg_t {
 	/** If true, then skip allocating this rseg as it reside in
 	UNDO-tablespace marked for truncate. */
 	bool				skip_allocation;
+
+	/** @return whether the rollback segment is persistent */
+	bool is_persistent() const
+	{
+		ut_ad(space == SRV_TMP_SPACE_ID
+		      || space <= srv_undo_tablespaces);
+		return(space != SRV_TMP_SPACE_ID);
+	}
 };
 
 /* Undo log segment slot in a rollback segment header */
diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h
index 8ebb74e3d86..8ecf264804c 100644
--- a/storage/innobase/include/trx0sys.h
+++ b/storage/innobase/include/trx0sys.h
@@ -75,17 +75,10 @@ Creates and initializes the transaction system at the database creation. */
 void
 trx_sys_create_sys_pages(void);
 /*==========================*/
-/****************************************************************//**
-Looks for a free slot for a rollback segment in the trx system file copy.
- at return slot index or ULINT_UNDEFINED if not found */
+/** @return an unallocated rollback segment slot in the TRX_SYS header
+ at retval ULINT_UNDEFINED if not found */
 ulint
-trx_sysf_rseg_find_free(
-/*====================*/
-	mtr_t*	mtr,			/*!< in/out: mtr */
-	bool	include_tmp_slots,	/*!< in: if true, report slots reserved
-					for temp-tablespace as free slots. */
-	ulint	nth_free_slots);	/*!< in: allocate nth free slot.
-					0 means next free slot. */
+trx_sysf_rseg_find_free(mtr_t* mtr);
 /**********************************************************************//**
 Gets a pointer to the transaction system file copy and x-locks its page.
 @return pointer to system file copy, page x-locked */
@@ -161,14 +154,6 @@ extern uint			trx_rseg_n_slots_debug;
 #endif
 
 /*****************************************************************//**
-Check if slot-id is reserved slot-id for noredo rsegs. */
-UNIV_INLINE
-bool
-trx_sys_is_noredo_rseg_slot(
-/*========================*/
-	ulint	slot_id);	/*!< in: slot_id to check */
-
-/*****************************************************************//**
 Writes a trx id to an index page. In case that the id size changes in
 some future version, this function should be used instead of
 mach_write_... */
@@ -319,16 +304,10 @@ trx_sys_file_format_max_set(
 	ulint		format_id,	/*!< in: file format id */
 	const char**	name);		/*!< out: max file format name or
 					NULL if not needed. */
-/*********************************************************************
-Creates the rollback segments
- at return number of rollback segments that are active. */
-ulint
-trx_sys_create_rsegs(
-/*=================*/
-	ulint	n_spaces,	/*!< number of tablespaces for UNDO logs */
-	ulint	n_rsegs,	/*!< number of rollback segments to create */
-	ulint	n_tmp_rsegs);	/*!< number of rollback segments reserved for
-				temp-tables. */
+/** Create the rollback segments.
+ at return	whether the creation succeeded */
+bool
+trx_sys_create_rsegs();
 /*****************************************************************//**
 Get the number of transaction in the system, independent of their state.
 @return count of transactions in trx_sys_t::trx_list */
@@ -583,6 +562,10 @@ struct trx_sys_t {
 					consistent snapshot. */
 
 	char		pad3[64];	/*!< To avoid false sharing */
+	/** Temporary rollback segments */
+	trx_rseg_t*	temp_rsegs[TRX_SYS_N_RSEGS];
+	char		pad4[64];	/*!< To avoid false sharing */
+
 	trx_rseg_t*	rseg_array[TRX_SYS_N_RSEGS];
 					/*!< Pointer array to rollback
 					segments; NULL if slot not in use;
diff --git a/storage/innobase/include/trx0sys.ic b/storage/innobase/include/trx0sys.ic
index f03535c53b3..1c805ead4b3 100644
--- a/storage/innobase/include/trx0sys.ic
+++ b/storage/innobase/include/trx0sys.ic
@@ -192,18 +192,6 @@ trx_write_trx_id(
 }
 
 /*****************************************************************//**
-Check if slot-id is reserved slot-id for noredo rsegs. */
-UNIV_INLINE
-bool
-trx_sys_is_noredo_rseg_slot(
-/*========================*/
-	ulint	slot_id)	/*!< in: slot_id to check */
-{
-	/* Slots allocated from temp-tablespace are no-redo slots. */
-	return(slot_id > 0 && slot_id < (srv_tmp_undo_logs + 1));
-}
-
-/*****************************************************************//**
 Reads a trx id from an index page. In case that the id size changes in
 some future version, this function should be used instead of
 mach_read_...
diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h
index 7da3bfb5459..d0a67a7ed28 100644
--- a/storage/innobase/include/trx0trx.h
+++ b/storage/innobase/include/trx0trx.h
@@ -507,14 +507,6 @@ trx_id_t
 trx_get_id_for_print(
 	const trx_t*	trx);
 
-/****************************************************************//**
-Assign a transaction temp-tablespace bound rollback-segment. */
-void
-trx_assign_rseg(
-/*============*/
-	trx_t*		trx);		/*!< transaction that involves write
-					to temp-table. */
-
 /** Create the trx_t pool */
 void
 trx_pool_init();
@@ -869,12 +861,6 @@ struct trx_rsegs_t {
 	trx_temp_undo_t	m_noredo;
 };
 
-enum trx_rseg_type_t {
-	TRX_RSEG_TYPE_NONE = 0,		/*!< void rollback segment type. */
-	TRX_RSEG_TYPE_REDO,		/*!< redo rollback segment. */
-	TRX_RSEG_TYPE_NOREDO		/*!< non-redo rollback segment. */
-};
-
 struct TrxVersion {
 	TrxVersion(trx_t* trx);
 
@@ -1295,6 +1281,22 @@ struct trx_t {
 	{
 		return(has_logged_persistent() || rsegs.m_noredo.undo);
 	}
+
+	/** @return rollback segment for modifying temporary tables */
+	trx_rseg_t* get_temp_rseg()
+	{
+		if (trx_rseg_t* rseg = rsegs.m_noredo.rseg) {
+			ut_ad(id != 0);
+			return(rseg);
+		}
+
+		return(assign_temp_rseg());
+	}
+
+private:
+	/** Assign a rollback segment for modifying temporary tables.
+	@return the assigned rollback segment */
+	trx_rseg_t* assign_temp_rseg();
 };
 
 /**
diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc
index ce9a265bd8c..2a13203b747 100644
--- a/storage/innobase/row/row0purge.cc
+++ b/storage/innobase/row/row0purge.cc
@@ -741,10 +741,11 @@ row_purge_upd_exist_or_extern_func(
 						 &is_insert, &rseg_id,
 						 &page_no, &offset);
 
-			rseg = trx_rseg_get_on_id(rseg_id);
+			rseg = trx_sys->rseg_array[rseg_id];
 
 			ut_a(rseg != NULL);
-			ut_a(rseg->id == rseg_id);
+			ut_ad(rseg->id == rseg_id);
+			ut_ad(rseg->is_persistent());
 
 			mtr_start(&mtr);
 
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index b689cd012c6..a05bb5300a3 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -139,10 +139,6 @@ my_bool	srv_undo_log_truncate = FALSE;
 /** Maximum size of undo tablespace. */
 unsigned long long	srv_max_undo_log_size;
 
-/** UNDO logs that are not redo logged.
-These logs reside in the temp tablespace.*/
-const ulong		srv_tmp_undo_logs = 32;
-
 /** Default undo tablespace size in UNIV_PAGEs count (10MB). */
 const ulint SRV_UNDO_TABLESPACE_SIZE_IN_PAGES =
 	((1024 * 1024) * 10) / UNIV_PAGE_SIZE_DEF;
@@ -403,37 +399,38 @@ UNIV_INTERN ulong	srv_n_spin_wait_rounds	= 15;
 uint	srv_spin_wait_delay;
 ibool	srv_priority_boost	= TRUE;
 
-static ulint		srv_n_rows_inserted_old		= 0;
-static ulint		srv_n_rows_updated_old		= 0;
-static ulint		srv_n_rows_deleted_old		= 0;
-static ulint		srv_n_rows_read_old		= 0;
-static ulint		srv_n_system_rows_inserted_old	= 0;
-static ulint		srv_n_system_rows_updated_old	= 0;
-static ulint		srv_n_system_rows_deleted_old	= 0;
-static ulint		srv_n_system_rows_read_old	= 0;
-
-ulint	srv_truncated_status_writes	= 0;
-ulint	srv_available_undo_logs         = 0;
-
-UNIV_INTERN ib_uint64_t srv_page_compression_saved      = 0;
-UNIV_INTERN ib_uint64_t srv_page_compression_trim_sect512       = 0;
-UNIV_INTERN ib_uint64_t srv_page_compression_trim_sect4096      = 0;
-UNIV_INTERN ib_uint64_t srv_index_pages_written         = 0;
-UNIV_INTERN ib_uint64_t srv_non_index_pages_written     = 0;
-UNIV_INTERN ib_uint64_t srv_pages_page_compressed       = 0;
-UNIV_INTERN ib_uint64_t srv_page_compressed_trim_op     = 0;
-UNIV_INTERN ib_uint64_t srv_page_compressed_trim_op_saved     = 0;
-UNIV_INTERN ib_uint64_t srv_index_page_decompressed     = 0;
+static ulint		srv_n_rows_inserted_old;
+static ulint		srv_n_rows_updated_old;
+static ulint		srv_n_rows_deleted_old;
+static ulint		srv_n_rows_read_old;
+static ulint		srv_n_system_rows_inserted_old;
+static ulint		srv_n_system_rows_updated_old;
+static ulint		srv_n_system_rows_deleted_old;
+static ulint		srv_n_system_rows_read_old;
+
+ulint	srv_truncated_status_writes;
+/** Number of initialized rollback segments for persistent undo log */
+ulong	srv_available_undo_logs;
+
+UNIV_INTERN ib_uint64_t srv_page_compression_saved;
+UNIV_INTERN ib_uint64_t srv_page_compression_trim_sect512;
+UNIV_INTERN ib_uint64_t srv_page_compression_trim_sect4096;
+UNIV_INTERN ib_uint64_t srv_index_pages_written;
+UNIV_INTERN ib_uint64_t srv_non_index_pages_written;
+UNIV_INTERN ib_uint64_t srv_pages_page_compressed;
+UNIV_INTERN ib_uint64_t srv_page_compressed_trim_op;
+UNIV_INTERN ib_uint64_t srv_page_compressed_trim_op_saved;
+UNIV_INTERN ib_uint64_t srv_index_page_decompressed;
 
 /* Defragmentation */
-UNIV_INTERN my_bool	srv_defragment = FALSE;
+UNIV_INTERN my_bool	srv_defragment;
 UNIV_INTERN uint	srv_defragment_n_pages = 7;
-UNIV_INTERN uint	srv_defragment_stats_accuracy = 0;
+UNIV_INTERN uint	srv_defragment_stats_accuracy;
 UNIV_INTERN uint	srv_defragment_fill_factor_n_recs = 20;
 UNIV_INTERN double	srv_defragment_fill_factor = 0.9;
 UNIV_INTERN uint	srv_defragment_frequency =
 	SRV_DEFRAGMENT_FREQUENCY_DEFAULT;
-UNIV_INTERN ulonglong	srv_defragment_interval = 0;
+UNIV_INTERN ulonglong	srv_defragment_interval;
 
 /* Set the following to 0 if you want InnoDB to write messages on
 stderr on startup/shutdown. */
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 7c16ce1e58f..bcb52fc5bfb 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -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.
+ at 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";
-
-		ib::info() << srv_undo_tablespaces_active << " undo tablespaces"
-			<< " made active";
+			<< " undo tablespaces ("
+			<< srv_undo_tablespaces_active
+			<< " 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 @@ innobase_start_or_create_for_mysql(void)
 	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 @@ innobase_start_or_create_for_mysql(void)
 	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));
 	}
 
diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc
index 6ff4c882be8..f83d9377852 100644
--- a/storage/innobase/trx/trx0purge.cc
+++ b/storage/innobase/trx/trx0purge.cc
@@ -327,17 +327,12 @@ trx_purge_remove_log_hdr(
 	my_atomic_addlint(&trx_sys->rseg_history_len, -1);
 }
 
-/** Frees an undo log segment which is in the history list. Removes the
-undo log hdr from the history list.
+/** Free an undo log segment, and remove the header from the history list.
 @param[in,out]	rseg		rollback segment
- at param[in]	hdr_addr	file address of log_hdr
- at param[in]	noredo		skip redo logging. */
+ at param[in]	hdr_addr	file address of log_hdr */
 static
 void
-trx_purge_free_segment(
-	trx_rseg_t*	rseg,
-	fil_addr_t	hdr_addr,
-	bool		noredo)
+trx_purge_free_segment(trx_rseg_t* rseg, fil_addr_t hdr_addr)
 {
 	mtr_t		mtr;
 	trx_rsegf_t*	rseg_hdr;
@@ -345,16 +340,12 @@ trx_purge_free_segment(
 	trx_usegf_t*	seg_hdr;
 	ulint		seg_size;
 	ulint		hist_size;
-	bool		marked		= noredo;
+	bool		marked		= false;
 
 	for (;;) {
 		page_t*	undo_page;
 
 		mtr_start(&mtr);
-		if (noredo) {
-			mtr.set_log_mode(MTR_LOG_NO_REDO);
-		}
-		ut_ad(noredo == trx_sys_is_noredo_rseg_slot(rseg->id));
 
 		mutex_enter(&rseg->mutex);
 
@@ -428,14 +419,12 @@ trx_purge_free_segment(
 	mtr_commit(&mtr);
 }
 
-/********************************************************************//**
-Removes unnecessary history data from a rollback segment. */
+/** Remove unnecessary history data from a rollback segment.
+ at param[in,out]	rseg		rollback segment
+ at param[in]	limit		truncate offset */
 static
 void
-trx_purge_truncate_rseg_history(
-/*============================*/
-	trx_rseg_t*		rseg,		/*!< in: rollback segment */
-	const purge_iter_t*	limit)		/*!< in: truncate offset */
+trx_purge_truncate_rseg_history(trx_rseg_t* rseg, const purge_iter_t* limit)
 {
 	fil_addr_t	hdr_addr;
 	fil_addr_t	prev_hdr_addr;
@@ -445,13 +434,9 @@ trx_purge_truncate_rseg_history(
 	trx_usegf_t*	seg_hdr;
 	mtr_t		mtr;
 	trx_id_t	undo_trx_no;
-	const bool	noredo		= trx_sys_is_noredo_rseg_slot(
-		rseg->id);
 
 	mtr_start(&mtr);
-	if (noredo) {
-		mtr.set_log_mode(MTR_LOG_NO_REDO);
-	}
+	ut_ad(rseg->is_persistent());
 	mutex_enter(&(rseg->mutex));
 
 	rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr);
@@ -509,7 +494,7 @@ trx_purge_truncate_rseg_history(
 
 		/* calls the trx_purge_remove_log_hdr()
 		inside trx_purge_free_segment(). */
-		trx_purge_free_segment(rseg, hdr_addr, noredo);
+		trx_purge_free_segment(rseg, hdr_addr);
 	} else {
 		/* Remove the log hdr from the rseg history. */
 		trx_purge_remove_log_hdr(rseg_hdr, log_hdr, &mtr);
@@ -519,9 +504,6 @@ trx_purge_truncate_rseg_history(
 	}
 
 	mtr_start(&mtr);
-	if (noredo) {
-		mtr.set_log_mode(MTR_LOG_NO_REDO);
-	}
 	mutex_enter(&(rseg->mutex));
 
 	rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr);
@@ -806,10 +788,9 @@ trx_purge_mark_undo_for_truncate(
 	/* Step-2: Validation/Qualification checks
 	a. At-least 2 UNDO tablespaces so even if one UNDO tablespace
 	   is being truncated server can continue to operate.
-	b. At-least 2 UNDO redo rseg/undo logs (besides the default rseg-0)
+	b. At-least 2 persistent UNDO logs (besides the default rseg-0)
 	b. At-least 1 UNDO tablespace size > threshold. */
-	if (srv_undo_tablespaces_active < 2
-	    || (srv_undo_logs < (1 + srv_tmp_undo_logs + 2))) {
+	if (srv_undo_tablespaces_active < 2 || srv_undo_logs < 3) {
 		return;
 	}
 
@@ -846,11 +827,9 @@ trx_purge_mark_undo_for_truncate(
 	/* Step-3: Iterate over all the rsegs of selected UNDO tablespace
 	and mark them temporarily unavailable for allocation.*/
 	for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) {
-		trx_rseg_t*	rseg = trx_sys->rseg_array[i];
-
-		if (rseg != NULL && !trx_sys_is_noredo_rseg_slot(rseg->id)) {
-			if (rseg->space
-				== undo_trunc->get_marked_space_id()) {
+		if (trx_rseg_t* rseg = trx_sys->rseg_array[i]) {
+			ut_ad(rseg->is_persistent());
+			if (rseg->space == undo_trunc->get_marked_space_id()) {
 
 				/* Once set this rseg will not be allocated
 				to new booting transaction but we will wait
diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc
index 481e14d44de..47d24b63114 100644
--- a/storage/innobase/trx/trx0rec.cc
+++ b/storage/innobase/trx/trx0rec.cc
@@ -1893,13 +1893,7 @@ trx_undo_report_row_operation(
 	if (is_temp) {
 		mtr.set_log_mode(MTR_LOG_NO_REDO);
 
-		rseg = trx->rsegs.m_noredo.rseg;
-
-		if (!rseg) {
-			trx_assign_rseg(trx);
-			rseg = trx->rsegs.m_noredo.rseg;
-		}
-
+		rseg = trx->get_temp_rseg();
 		pundo = &trx->rsegs.m_noredo.undo;
 	} else {
 		ut_ad(!trx->read_only);
@@ -2057,16 +2051,16 @@ trx_undo_report_row_operation(
 
 /*============== BUILDING PREVIOUS VERSION OF A RECORD ===============*/
 
-/******************************************************************//**
-Copies an undo record to heap. This function can be called if we know that
-the undo log record exists.
- at return own: copy of the record */
+/** Copy an undo record to heap.
+ at param[in]	roll_ptr	roll pointer to a record that exists
+ at param[in]	is_temp		whether this is a temporary table
+ at param[in,out]	heap		memory heap where copied */
 static
 trx_undo_rec_t*
 trx_undo_get_undo_rec_low(
-/*======================*/
-	roll_ptr_t	roll_ptr,	/*!< in: roll pointer to record */
-	mem_heap_t*	heap)		/*!< in: memory heap where copied */
+	roll_ptr_t	roll_ptr,
+	bool		is_temp,
+	mem_heap_t*	heap)
 {
 	trx_undo_rec_t*	undo_rec;
 	ulint		rseg_id;
@@ -2079,7 +2073,10 @@ trx_undo_get_undo_rec_low(
 
 	trx_undo_decode_roll_ptr(roll_ptr, &is_insert, &rseg_id, &page_no,
 				 &offset);
-	rseg = trx_rseg_get_on_id(rseg_id);
+	rseg = is_temp
+		? trx_sys->temp_rsegs[rseg_id]
+		: trx_sys->rseg_array[rseg_id];
+	ut_ad(is_temp == !rseg->is_persistent());
 
 	mtr_start(&mtr);
 
@@ -2093,13 +2090,13 @@ trx_undo_get_undo_rec_low(
 	return(undo_rec);
 }
 
-/******************************************************************//**
-Copies an undo record to heap.
+/** Copy an undo record to heap.
 @param[in]	roll_ptr	roll pointer to record
+ at param[in]	is_temp		whether this is a temporary table
+ at param[in,out]	heap		memory heap where copied
 @param[in]	trx_id		id of the trx that generated
 				the roll pointer: it points to an
 				undo log of this transaction
- at param[in]	heap		memory heap where copied
 @param[in]	name		table name
 @param[out]	undo_rec	own: copy of the record
 @retval true if the undo log has been
@@ -2109,10 +2106,10 @@ NOTE: the caller must have latches on the clustered index page. */
 static MY_ATTRIBUTE((warn_unused_result))
 bool
 trx_undo_get_undo_rec(
-/*==================*/
 	roll_ptr_t		roll_ptr,
-	trx_id_t		trx_id,
+	bool			is_temp,
 	mem_heap_t*		heap,
+	trx_id_t		trx_id,
 	const table_name_t&	name,
 	trx_undo_rec_t**	undo_rec)
 {
@@ -2122,7 +2119,7 @@ trx_undo_get_undo_rec(
 
 	missing_history = purge_sys->view.changes_visible(trx_id, name);
 	if (!missing_history) {
-		*undo_rec = trx_undo_get_undo_rec_low(roll_ptr, heap);
+		*undo_rec = trx_undo_get_undo_rec_low(roll_ptr, is_temp, heap);
 	}
 
 	rw_lock_s_unlock(&purge_sys->latch);
@@ -2203,13 +2200,17 @@ trx_undo_prev_version_build(
 		return(true);
 	}
 
+	const bool is_temp = dict_table_is_temporary(index->table);
 	rec_trx_id = row_get_rec_trx_id(rec, index, offsets);
 
 	if (trx_undo_get_undo_rec(
-		roll_ptr, rec_trx_id, heap, index->table->name, &undo_rec)) {
+		    roll_ptr, is_temp, heap, rec_trx_id, index->table->name,
+		    &undo_rec)) {
 		if (v_status & TRX_UNDO_PREV_IN_PURGE) {
 			/* We are fetching the record being purged */
-			undo_rec = trx_undo_get_undo_rec_low(roll_ptr, heap);
+			ut_ad(!is_temp);
+			undo_rec = trx_undo_get_undo_rec_low(
+				roll_ptr, is_temp, heap);
 		} else {
 			/* The undo record may already have been purged,
 			during purge or semi-consistent read. */
diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc
index 883e2eb60b2..3393a0464a8 100644
--- a/storage/innobase/trx/trx0rseg.cc
+++ b/storage/innobase/trx/trx0rseg.cc
@@ -90,12 +90,7 @@ trx_rseg_header_create(
 		trx_rsegf_set_nth_undo(rsegf, i, FIL_NULL, mtr);
 	}
 
-	if (!trx_sys_is_noredo_rseg_slot(rseg_slot_no)) {
-		/* Non-redo rseg are re-created on restart and so no need
-		to persist this information in sys-header. Anyway, on restart
-		this information is not valid too as there is no space with
-		persisted space-id on restart. */
-
+	if (space != SRV_TMP_SPACE_ID) {
 		/* Add the rollback segment info to the free slot in
 		the trx system header */
 
@@ -152,51 +147,48 @@ trx_rseg_mem_free(trx_rseg_t* rseg)
 	ut_free(rseg);
 }
 
-/** Creates and initializes a rollback segment object.
-The values for the fields are read from the header. The object is inserted to
-the rseg list of the trx system object and a pointer is inserted in the rseg
-array in the trx system object.
+/** Create a rollback segment object.
 @param[in]	id		rollback segment id
 @param[in]	space		space where the segment is placed
- at param[in]	page_no		page number of the segment header
- at param[in,out]	mtr		mini-transaction */
+ at param[in]	page_no		page number of the segment header */
 static
-void
-trx_rseg_mem_create(
-	ulint			id,
-	ulint			space,
-	ulint			page_no,
-	mtr_t*			mtr)
+trx_rseg_t*
+trx_rseg_mem_create(ulint id, ulint space, ulint page_no)
 {
-	ulint		len;
-	trx_rseg_t*	rseg;
-	fil_addr_t	node_addr;
-	trx_rsegf_t*	rseg_header;
-	trx_ulogf_t*	undo_log_hdr;
-	ulint		sum_of_undo_sizes;
-
-	rseg = static_cast<trx_rseg_t*>(ut_zalloc_nokey(sizeof(trx_rseg_t)));
+	trx_rseg_t* rseg = static_cast<trx_rseg_t*>(
+		ut_zalloc_nokey(sizeof *rseg));
 
 	rseg->id = id;
 	rseg->space = space;
 	rseg->page_no = page_no;
-	rseg->trx_ref_count = 0;
-	rseg->skip_allocation = false;
+	rseg->last_page_no = FIL_NULL;
 
-	if (fsp_is_system_temporary(space)) {
-		mutex_create(LATCH_ID_NOREDO_RSEG, &rseg->mutex);
-	} else {
-		mutex_create(LATCH_ID_REDO_RSEG, &rseg->mutex);
-	}
+	mutex_create(rseg->is_persistent()
+		     ? LATCH_ID_REDO_RSEG : LATCH_ID_NOREDO_RSEG,
+		     &rseg->mutex);
 
 	UT_LIST_INIT(rseg->update_undo_list, &trx_undo_t::undo_list);
 	UT_LIST_INIT(rseg->update_undo_cached, &trx_undo_t::undo_list);
 	UT_LIST_INIT(rseg->insert_undo_list, &trx_undo_t::undo_list);
 	UT_LIST_INIT(rseg->insert_undo_cached, &trx_undo_t::undo_list);
 
-	trx_sys->rseg_array[id] = rseg;
+	return(rseg);
+}
+
+/** Restore the state of a persistent rollback segment.
+ at param[in,out]	rseg	persistent rollback segment
+ at param[in,out]	mtr	mini-transaction */
+static
+void
+trx_rseg_mem_restore(trx_rseg_t* rseg, mtr_t* mtr)
+{
+	ulint		len;
+	fil_addr_t	node_addr;
+	trx_rsegf_t*	rseg_header;
+	trx_ulogf_t*	undo_log_hdr;
+	ulint		sum_of_undo_sizes;
 
-	rseg_header = trx_rsegf_get_new(space, page_no, mtr);
+	rseg_header = trx_rsegf_get_new(rseg->space, rseg->page_no, mtr);
 
 	rseg->max_size = mtr_read_ulint(
 		rseg_header + TRX_RSEG_MAX_SIZE, MLOG_4BYTES, mtr);
@@ -240,8 +232,6 @@ trx_rseg_mem_create(
 
 			purge_sys->purge_queue.push(elem);
 		}
-	} else {
-		rseg->last_page_no = FIL_NULL;
 	}
 }
 
@@ -252,54 +242,45 @@ trx_rseg_array_init()
 	mtr_t	mtr;
 
 	for (ulint i = 0; i < TRX_SYS_N_RSEGS; i++) {
-		ut_ad(!trx_rseg_get_on_id(i));
 		mtr.start();
 		trx_sysf_t*	sys_header = trx_sysf_get(&mtr);
 		ulint		page_no = trx_sysf_rseg_get_page_no(
 			sys_header, i, &mtr);
 
 		if (page_no != FIL_NULL) {
-			trx_rseg_mem_create(
+			trx_rseg_t* rseg = trx_rseg_mem_create(
 				i,
 				trx_sysf_rseg_get_space(sys_header, i, &mtr),
-				page_no, &mtr);
+				page_no);
+			ut_ad(rseg->is_persistent());
+			ut_ad(!trx_sys->rseg_array[rseg->id]);
+			trx_sys->rseg_array[rseg->id] = rseg;
+			trx_rseg_mem_restore(rseg, &mtr);
 		}
 
 		mtr.commit();
 	}
 }
 
-/*********************************************************************
-Creates a rollback segment.
- at return pointer to new rollback segment if create successful */
+/** Create a persistent rollback segment.
+ at param[in]	space_id	system or undo tablespace id */
 trx_rseg_t*
-trx_rseg_create(
-/*============*/
-	ulint	space_id,	/*!< in: id of UNDO tablespace */
-	ulint	nth_free_slot)	/*!< in: allocate nth free slot.
-				0 means next free slots. */
+trx_rseg_create(ulint space_id)
 {
-	mtr_t		mtr;
+	trx_rseg_t*		rseg = NULL;
+	mtr_t			mtr;
 
 	mtr.start();
 
 	/* To obey the latching order, acquire the file space
 	x-latch before the trx_sys->mutex. */
-	const fil_space_t*	space = mtr_x_lock_space(space_id, &mtr);
+#ifdef UNIV_DEBUG
+	const fil_space_t*	space =
+#endif /* UNIV_DEBUG */
+		mtr_x_lock_space(space_id, &mtr);
+	ut_ad(space->purpose == FIL_TYPE_TABLESPACE);
 
-	switch (space->purpose) {
-	case FIL_TYPE_LOG:
-	case FIL_TYPE_IMPORT:
-		ut_ad(0);
-	case FIL_TYPE_TEMPORARY:
-		mtr.set_log_mode(MTR_LOG_NO_REDO);
-		break;
-	case FIL_TYPE_TABLESPACE:
-		break;
-	}
-
-	ulint	slot_no = trx_sysf_rseg_find_free(
-		&mtr, space->purpose == FIL_TYPE_TEMPORARY, nth_free_slot);
+	ulint	slot_no = trx_sysf_rseg_find_free(&mtr);
 	ulint	page_no = slot_no == ULINT_UNDEFINED
 		? FIL_NULL
 		: trx_rseg_header_create(space_id, ULINT_MAX, slot_no, &mtr);
@@ -309,14 +290,45 @@ trx_rseg_create(
 
 		ulint		id = trx_sysf_rseg_get_space(
 			sys_header, slot_no, &mtr);
-		ut_a(id == space_id || trx_sys_is_noredo_rseg_slot(slot_no));
+		ut_a(id == space_id);
 
-		trx_rseg_mem_create(slot_no, space_id, page_no, &mtr);
+		rseg = trx_rseg_mem_create(slot_no, space_id, page_no);
+		ut_ad(rseg->is_persistent());
+		ut_ad(!trx_sys->rseg_array[rseg->id]);
+		trx_sys->rseg_array[rseg->id] = rseg;
+		trx_rseg_mem_restore(rseg, &mtr);
 	}
 
 	mtr.commit();
 
-	return(page_no == FIL_NULL ? NULL : trx_sys->rseg_array[slot_no]);
+	return(rseg);
+}
+
+/** Create the temporary rollback segments. */
+void
+trx_temp_rseg_create()
+{
+	mtr_t		mtr;
+
+	for (ulong i = 0; i < TRX_SYS_N_RSEGS; i++) {
+		mtr.start();
+		mtr.set_log_mode(MTR_LOG_NO_REDO);
+#ifdef UNIV_DEBUG
+		const fil_space_t*	space =
+#endif /* UNIV_DEBUG */
+			mtr_x_lock_space(SRV_TMP_SPACE_ID, &mtr);
+		ut_ad(space->purpose == FIL_TYPE_TEMPORARY);
+
+		ulint page_no = trx_rseg_header_create(
+			SRV_TMP_SPACE_ID, ULINT_MAX, i, &mtr);
+		trx_rseg_t* rseg = trx_rseg_mem_create(
+			i, SRV_TMP_SPACE_ID, page_no);
+		ut_ad(!rseg->is_persistent());
+		ut_ad(!trx_sys->temp_rsegs[i]);
+		trx_sys->temp_rsegs[i] = rseg;
+		trx_rseg_mem_restore(rseg, &mtr);
+		mtr.commit();
+	}
 }
 
 /********************************************************************
diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc
index f08736ae1f1..24983dcc2a3 100644
--- a/storage/innobase/trx/trx0sys.cc
+++ b/storage/innobase/trx/trx0sys.cc
@@ -394,76 +394,41 @@ trx_sys_read_wsrep_checkpoint(
 
 #endif /* WITH_WSREP */
 
-/****************************************************************//**
-Looks for a free slot for a rollback segment in the trx system file copy.
- at return slot index or ULINT_UNDEFINED if not found */
+/** @return an unallocated rollback segment slot in the TRX_SYS header
+ at retval ULINT_UNDEFINED if not found */
 ulint
-trx_sysf_rseg_find_free(
-/*====================*/
-	mtr_t*	mtr,			/*!< in/out: mtr */
-	bool	include_tmp_slots,	/*!< in: if true, report slots reserved
-					for temp-tablespace as free slots. */
-	ulint	nth_free_slots)		/*!< in: allocate nth free slot.
-					0 means next free slot. */
+trx_sysf_rseg_find_free(mtr_t* mtr)
 {
-	ulint		i;
-	trx_sysf_t*	sys_header;
-
-	sys_header = trx_sysf_get(mtr);
-
-	ulint	found_free_slots = 0;
-	for (i = 0; i < TRX_SYS_N_RSEGS; i++) {
-		ulint	page_no;
-
-		if (!include_tmp_slots && trx_sys_is_noredo_rseg_slot(i)) {
-			continue;
-		}
-
-		page_no = trx_sysf_rseg_get_page_no(sys_header, i, mtr);
+	trx_sysf_t*	sys_header = trx_sysf_get(mtr);
 
-		if (page_no == FIL_NULL
-		    || (include_tmp_slots
-			&& trx_sys_is_noredo_rseg_slot(i))) {
-
-			if (found_free_slots++ >= nth_free_slots) {
-				return(i);
-			}
+	for (ulint i = 0; i < TRX_SYS_N_RSEGS; i++) {
+		if (trx_sysf_rseg_get_page_no(sys_header, i, mtr)
+		    == FIL_NULL) {
+			return(i);
 		}
 	}
 
 	return(ULINT_UNDEFINED);
 }
 
-/****************************************************************//**
-Looks for used slots for redo rollback segment.
- at return number of used slots */
+/** Count the number of initialized persistent rollback segment slots. */
 static
-ulint
-trx_sysf_used_slots_for_redo_rseg(
-/*==============================*/
-	mtr_t*	mtr)			/*!< in: mtr */
+void
+trx_sysf_get_n_rseg_slots()
 {
-	trx_sysf_t*	sys_header;
-	ulint		n_used = 0;
+	mtr_t		mtr;
+	mtr.start();
 
-	sys_header = trx_sysf_get(mtr);
+	trx_sysf_t*	sys_header	= trx_sysf_get(&mtr);
+	srv_available_undo_logs = 0;
 
 	for (ulint i = 0; i < TRX_SYS_N_RSEGS; i++) {
-
-		if (trx_sys_is_noredo_rseg_slot(i)) {
-			continue;
-		}
-
-		ulint	page_no;
-
-		page_no = trx_sysf_rseg_get_page_no(sys_header, i, mtr);
-
-		if (page_no != FIL_NULL) {
-			++n_used;
-		}
+		srv_available_undo_logs
+			+= trx_sysf_rseg_get_page_no(sys_header, i, &mtr)
+			!= FIL_NULL;
 	}
 
-	return(n_used);
+	mtr.commit();
 }
 
 /*****************************************************************//**
@@ -532,7 +497,7 @@ trx_sysf_create(
 			+ page - sys_header, mtr);
 
 	/* Create the first rollback segment in the SYSTEM tablespace */
-	slot_no = trx_sysf_rseg_find_free(mtr, false, 0);
+	slot_no = trx_sysf_rseg_find_free(mtr);
 	page_no = trx_rseg_header_create(TRX_SYS_SPACE,
 					 ULINT_MAX, slot_no, mtr);
 
@@ -904,118 +869,69 @@ trx_sys_file_format_close(void)
 	mutex_free(&file_format_max.mutex);
 }
 
-/*********************************************************************
-Creates non-redo rollback segments.
- at return number of non-redo rollback segments created. */
-static
-ulint
-trx_sys_create_noredo_rsegs(
-/*========================*/
-	ulint	n_nonredo_rseg)	/*!< number of non-redo rollback segment
-				to create. */
-{
-	ulint n_created = 0;
-
-	/* Create non-redo rollback segments residing in temp-tablespace.
-	non-redo rollback segments don't perform redo logging and so
-	are used for undo logging of objects/table that don't need to be
-	recover on crash.
-	(Non-Redo rollback segments are created on every server startup).
-	Slot-0: reserved for system-tablespace.
-	Slot-1....Slot-N: reserved for temp-tablespace.
-	Slot-N+1....Slot-127: reserved for system/undo-tablespace. */
-	for (ulint i = 0; i < n_nonredo_rseg; i++) {
-		if (trx_rseg_create(SRV_TMP_SPACE_ID, i) == NULL) {
-			break;
-		}
-		++n_created;
-	}
-
-	return(n_created);
-}
-
-/*********************************************************************
-Creates the rollback segments.
- at return number of rollback segments that are active. */
-ulint
-trx_sys_create_rsegs(
-/*=================*/
-	ulint	n_spaces,	/*!< number of tablespaces for UNDO logs */
-	ulint	n_rsegs,	/*!< number of rollback segments to create */
-	ulint	n_tmp_rsegs)	/*!< number of rollback segments reserved for
-				temp-tables. */
+/** Create the rollback segments.
+ at return	whether the creation succeeded */
+bool
+trx_sys_create_rsegs()
 {
-	mtr_t	mtr;
-	ulint	n_used;
-	ulint	n_noredo_created;
+	/* srv_available_undo_logs reflects the number of persistent
+	rollback segments that have been initialized in the
+	transaction system header page.
 
-	ut_a(n_spaces < TRX_SYS_N_RSEGS);
-	ut_a(n_rsegs <= TRX_SYS_N_RSEGS);
-	ut_a(n_tmp_rsegs > 0 && n_tmp_rsegs < TRX_SYS_N_RSEGS);
+	srv_undo_logs determines how many of the
+	srv_available_undo_logs rollback segments may be used for
+	logging new transactions. */
+	ut_ad(srv_undo_tablespaces < TRX_SYS_N_RSEGS);
+	ut_ad(srv_undo_logs <= TRX_SYS_N_RSEGS);
 
 	if (srv_read_only_mode) {
-		return(ULINT_UNDEFINED);
+		srv_undo_logs = srv_available_undo_logs = ULONG_UNDEFINED;
+		return(true);
 	}
 
-	/* Create non-redo rollback segments. */
-	n_noredo_created = trx_sys_create_noredo_rsegs(n_tmp_rsegs);
+	/* Create temporary rollback segments. */
+	trx_temp_rseg_create();
 
 	/* This is executed in single-threaded mode therefore it is not
 	necessary to use the same mtr in trx_rseg_create(). n_used cannot
 	change while the function is executing. */
-	mtr_start(&mtr);
-	n_used = trx_sysf_used_slots_for_redo_rseg(&mtr) + n_noredo_created;
-	mtr_commit(&mtr);
+	trx_sysf_get_n_rseg_slots();
 
-	ut_ad(n_used <= TRX_SYS_N_RSEGS);
+	ut_ad(srv_available_undo_logs <= TRX_SYS_N_RSEGS);
 
-	/* By default 1 redo rseg is always active that is hosted in
-	system tablespace. */
-	ulint	n_redo_active;
-	if (n_rsegs <= n_tmp_rsegs) {
-		n_redo_active = 1;
-	} else if (n_rsegs > n_used) {
-		n_redo_active = n_used - n_tmp_rsegs;
-	} else {
-		n_redo_active = n_rsegs - n_tmp_rsegs;
-	}
-
-	/* Do not create additional rollback segments if innodb_force_recovery
-	has been set and the database was not shutdown cleanly. */
-	if (!srv_force_recovery && !recv_needed_recovery && n_used < n_rsegs) {
-		ulint	i;
-		ulint	new_rsegs = n_rsegs - n_used;
-
-		for (i = 0; i < new_rsegs; ++i) {
-			ulint	space;
-
-			/* Tablespace 0 is the system tablespace. All UNDO
-			log tablespaces start from 1. */
+	/* The first persistent rollback segment is always initialized
+	in the system tablespace. */
+	ut_a(srv_available_undo_logs > 0);
 
-			if (n_spaces > 0) {
-				space = (i % n_spaces) + 1;
-			} else {
-				space = 0; /* System tablespace */
-			}
-
-			if (trx_rseg_create(space, 0) != NULL) {
-				++n_used;
-				++n_redo_active;
-			} else {
-				break;
+	if (srv_force_recovery) {
+		/* Do not create additional rollback segments if
+		innodb_force_recovery has been set. */
+		if (srv_undo_logs > srv_available_undo_logs) {
+			srv_undo_logs = srv_available_undo_logs;
+		}
+	} else {
+		for (ulint i = 0; srv_available_undo_logs < srv_undo_logs;
+		     i++, srv_available_undo_logs++) {
+			/* Tablespace 0 is the system tablespace.
+			Dedicated undo log tablespaces start from 1. */
+			ulint space = srv_undo_tablespaces > 0
+				? (i % srv_undo_tablespaces) + 1
+				: TRX_SYS_SPACE;
+
+			if (!trx_rseg_create(space)) {
+				ib::error() << "Unable to allocate the"
+					" requested innodb_undo_logs";
+				return(false);
 			}
 		}
 	}
 
-	ib::info() << n_used - srv_tmp_undo_logs
-		<< " redo rollback segment(s) found. "
-		<< n_redo_active
-		<< " redo rollback segment(s) are active.";
+	ut_ad(srv_undo_logs <= srv_available_undo_logs);
 
-	ib::info() << n_noredo_created << " non-redo rollback segment(s) are"
-		" active.";
+	ib::info() << srv_undo_logs << " out of " << srv_available_undo_logs
+		<< " rollback segments are active.";
 
-	return(n_used);
+	return(true);
 }
 
 /*********************************************************************
@@ -1027,9 +943,7 @@ trx_sys_close(void)
 	ut_ad(trx_sys != NULL);
 	ut_ad(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS);
 
-	ulint	size = trx_sys->mvcc->size();
-
-	if (size > 0) {
+	if (ulint size = trx_sys->mvcc->size()) {
 		ib::error() << "All read views were not closed before"
 			" shutdown: " << size << " read views open";
 	}
@@ -1060,6 +974,10 @@ trx_sys_close(void)
 		if (trx_rseg_t* rseg = trx_sys->rseg_array[i]) {
 			trx_rseg_mem_free(rseg);
 		}
+
+		if (trx_rseg_t* rseg = trx_sys->temp_rsegs[i]) {
+			trx_rseg_mem_free(rseg);
+		}
 	}
 
 	UT_DELETE(trx_sys->mvcc);
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index b687f8e8990..55e2a096686 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -1095,37 +1095,11 @@ Get next redo rollback segment. (Segment are assigned in round-robin fashion).
 @return assigned rollback segment instance */
 static
 trx_rseg_t*
-get_next_redo_rseg(
-/*===============*/
-	ulong	max_undo_logs,	/*!< in: maximum number of UNDO logs to use */
-	ulint	n_tablespaces)	/*!< in: number of rollback tablespaces */
+get_next_redo_rseg()
 {
+	static ulong	rseg_slot;
+	ulint		slot = rseg_slot++ % srv_undo_logs;
 	trx_rseg_t*	rseg;
-	static ulint	redo_rseg_slot = 0;
-	ulint		slot = 0;
-
-	slot = redo_rseg_slot++;
-	slot = slot % max_undo_logs;
-
-	/* Skip slots alloted to non-redo also ensure even distribution
-	in selecting next redo slots.
-	For example: If we don't do even distribution then for any value of
-	slot between 1 - 32 ... 33rd slots will be alloted creating
-	skewed distribution. */
-	if (trx_sys_is_noredo_rseg_slot(slot)) {
-
-		if (max_undo_logs > srv_tmp_undo_logs) {
-
-			slot %= (max_undo_logs - srv_tmp_undo_logs);
-
-			if (trx_sys_is_noredo_rseg_slot(slot)) {
-				slot += srv_tmp_undo_logs;
-			}
-
-		} else {
-			slot = 0;
-		}
-	}
 
 #ifdef UNIV_DEBUG
 	ulint	start_scan_slot = slot;
@@ -1134,8 +1108,7 @@ get_next_redo_rseg(
 
 	bool	allocated = false;
 
-	while (!allocated) {
-
+	do {
 		for (;;) {
 			rseg = trx_sys->rseg_array[slot];
 
@@ -1148,37 +1121,31 @@ get_next_redo_rseg(
 			look_for_rollover = true;
 #endif /* UNIV_DEBUG */
 
-			slot = (slot + 1) % max_undo_logs;
-
-			/* Skip slots allocated for noredo rsegs */
-			while (trx_sys_is_noredo_rseg_slot(slot)) {
-				slot = (slot + 1) % max_undo_logs;
-			}
+			slot = (slot + 1) % srv_undo_logs;
 
 			if (rseg == NULL) {
 				continue;
-			} else if (rseg->space == srv_sys_space.space_id()
-				   && n_tablespaces > 0
-				   && trx_sys->rseg_array[slot] != NULL
-				   && trx_sys->rseg_array[slot]->space
-					!= srv_sys_space.space_id()) {
-				/** If undo-tablespace is configured, skip
-				rseg from system-tablespace and try to use
-				undo-tablespace rseg unless it is not possible
-				due to lower limit of undo-logs. */
-				continue;
-			} else if (rseg->skip_allocation) {
-				/** This rseg resides in the tablespace that
-				has been marked for truncate so avoid using this
-				rseg. Also, this is possible only if there are
-				at-least 2 UNDO tablespaces active and 2 redo
-				rsegs active (other than default system bound
-				rseg-0). */
-				ut_ad(n_tablespaces > 1);
-				ut_ad(max_undo_logs
-					>= (1 + srv_tmp_undo_logs + 2));
-				continue;
 			}
+
+			ut_ad(rseg->is_persistent());
+
+			if (rseg->space != TRX_SYS_SPACE) {
+				ut_ad(srv_undo_tablespaces > 1);
+				if (rseg->skip_allocation) {
+					continue;
+				}
+			} else if (trx_rseg_t* next
+				   = trx_sys->rseg_array[slot]) {
+				if (next->space != TRX_SYS_SPACE
+				    && srv_undo_tablespaces > 0) {
+					/** If dedicated
+					innodb_undo_tablespaces have
+					been configured, try to use them
+					instead of the system tablespace. */
+					continue;
+				}
+			}
+
 			break;
 		}
 
@@ -1191,129 +1158,65 @@ get_next_redo_rseg(
 			allocated = true;
 		}
 		mutex_exit(&rseg->mutex);
-	}
+	} while (!allocated);
 
 	ut_ad(rseg->trx_ref_count > 0);
-	ut_ad(!trx_sys_is_noredo_rseg_slot(rseg->id));
+	ut_ad(rseg->is_persistent());
 	return(rseg);
 }
 
-/******************************************************************//**
-Get next noredo rollback segment.
+/** Assign a rollback segment to a transaction in a round-robin fashion.
+ at param[in]	is_temp	whether to assign temporary undo log
 @return assigned rollback segment instance */
 static
 trx_rseg_t*
-get_next_noredo_rseg(
-/*=================*/
-	ulong	max_undo_logs)	/*!< in: maximum number of UNDO logs to use */
-{
-	trx_rseg_t*	rseg;
-	static ulint	noredo_rseg_slot = 1;
-	ulint		slot = 0;
-
-	slot = noredo_rseg_slot++;
-	slot = slot % max_undo_logs;
-	while (!trx_sys_is_noredo_rseg_slot(slot)) {
-		slot = (slot + 1) % max_undo_logs;
-	}
-
-	for (;;) {
-		rseg = trx_sys->rseg_array[slot];
-
-		slot = (slot + 1) % max_undo_logs;
-
-		while (!trx_sys_is_noredo_rseg_slot(slot)) {
-			slot = (slot + 1) % max_undo_logs;
-		}
-
-		if (rseg != NULL) {
-			break;
-		}
-	}
-
-	ut_ad(fsp_is_system_temporary(rseg->space));
-	ut_ad(trx_sys_is_noredo_rseg_slot(rseg->id));
-	return(rseg);
-}
-
-/******************************************************************//**
-Assigns a rollback segment to a transaction in a round-robin fashion.
- at return assigned rollback segment instance */
-static
-trx_rseg_t*
-trx_assign_rseg_low(
-/*================*/
-	ulong		max_undo_logs,	/*!< in: maximum number of UNDO logs
-					to use */
-	ulint		n_tablespaces,	/*!< in: number of rollback
-					tablespaces */
-	trx_rseg_type_t	rseg_type)	/*!< in: type of rseg to assign. */
+trx_assign_rseg_low()
 {
 	if (srv_read_only_mode) {
-		ut_a(max_undo_logs == ULONG_UNDEFINED);
+		ut_ad(srv_undo_logs == ULONG_UNDEFINED);
 		return(NULL);
 	}
 
 	/* This breaks true round robin but that should be OK. */
-	ut_ad(max_undo_logs > 0 && max_undo_logs <= TRX_SYS_N_RSEGS);
+	ut_ad(srv_undo_logs > 0);
+	ut_ad(srv_undo_logs <= TRX_SYS_N_RSEGS);
 
 	/* Note: The assumption here is that there can't be any gaps in
 	the array. Once we implement more flexible rollback segment
 	management this may not hold. The assertion checks for that case. */
 	ut_ad(trx_sys->rseg_array[0] != NULL);
-	ut_ad(rseg_type == TRX_RSEG_TYPE_REDO
-	      || trx_sys->rseg_array[1] != NULL);
 
 	/* Slot-0 is always assigned to system-tablespace rseg. */
-	ut_ad(trx_sys->rseg_array[0]->space == srv_sys_space.space_id());
-
-	/* Slot-1 is always assigned to temp-tablespace rseg. */
-	ut_ad(rseg_type == TRX_RSEG_TYPE_REDO
-	      || fsp_is_system_temporary(trx_sys->rseg_array[1]->space));
-
-	trx_rseg_t* rseg = 0;
-
-	switch (rseg_type) {
-	case TRX_RSEG_TYPE_NONE:
-		ut_error;
-
-	case TRX_RSEG_TYPE_REDO:
-		rseg = get_next_redo_rseg(max_undo_logs, n_tablespaces);
-		break;
+	ut_ad(trx_sys->rseg_array[0]->space == TRX_SYS_SPACE);
 
-	case TRX_RSEG_TYPE_NOREDO:
-		rseg = get_next_noredo_rseg(srv_tmp_undo_logs + 1);
-		break;
-	}
-
-	return(rseg);
+	return(get_next_redo_rseg());
 }
 
-/****************************************************************//**
-Assign a transaction temp-tablespace bounded rollback-segment. */
-void
-trx_assign_rseg(
-/*============*/
-	trx_t*		trx)		/*!< transaction that involves write
-					to temp-table. */
+/** Assign a rollback segment for modifying temporary tables.
+ at return the assigned rollback segment */
+trx_rseg_t*
+trx_t::assign_temp_rseg()
 {
-	ut_a(trx->rsegs.m_noredo.rseg == 0);
-	ut_a(!trx_is_autocommit_non_locking(trx));
+	ut_ad(!rsegs.m_noredo.rseg);
+	ut_ad(!trx_is_autocommit_non_locking(this));
+	compile_time_assert(ut_is_2pow(TRX_SYS_N_RSEGS));
 
-	trx->rsegs.m_noredo.rseg = trx_assign_rseg_low(
-		srv_undo_logs, srv_undo_tablespaces, TRX_RSEG_TYPE_NOREDO);
+	static ulong	slot;
+	trx_rseg_t*	rseg = trx_sys->temp_rsegs[
+		slot++ & (TRX_SYS_N_RSEGS - 1)];
+	ut_ad(!rseg->is_persistent());
+	rsegs.m_noredo.rseg = rseg;
 
-	if (trx->id == 0) {
+	if (id == 0) {
 		mutex_enter(&trx_sys->mutex);
-
-		trx->id = trx_sys_get_new_trx_id();
-
-		trx_sys->rw_trx_ids.push_back(trx->id);
-
-		trx_sys->rw_trx_set.insert(TrxTrack(trx->id, trx));
-
+		id = trx_sys_get_new_trx_id();
+		trx_sys->rw_trx_ids.push_back(id);
+		trx_sys->rw_trx_set.insert(TrxTrack(id, this));
 		mutex_exit(&trx_sys->mutex);
 	}
+
+	ut_ad(!rseg->is_persistent());
+	return(rseg);
 }
 
 /****************************************************************//**
@@ -1388,9 +1291,7 @@ trx_start_low(
 	if (!trx->read_only
 	    && (trx->mysql_thd == 0 || read_write || trx->ddl)) {
 
-		trx->rsegs.m_redo.rseg = trx_assign_rseg_low(
-			srv_undo_logs, srv_undo_tablespaces,
-			TRX_RSEG_TYPE_REDO);
+		trx->rsegs.m_redo.rseg = trx_assign_rseg_low();
 
 		/* Temporary rseg is assigned only if the transaction
 		updates a temporary table */
@@ -2969,8 +2870,6 @@ trx_start_if_not_started_xa_low(
 			trx_sys_t::rw_trx_list. */
 			if (!trx->read_only) {
 				trx_set_rw_mode(trx);
-			} else if (!srv_read_only_mode) {
-				trx_assign_rseg(trx);
 			}
 		}
 		return;
@@ -3116,8 +3015,7 @@ trx_set_rw_mode(
 	that both threads are synced by acquring trx->mutex to avoid decision
 	based on in-consistent view formed during promotion. */
 
-	trx->rsegs.m_redo.rseg = trx_assign_rseg_low(
-		srv_undo_logs, srv_undo_tablespaces, TRX_RSEG_TYPE_REDO);
+	trx->rsegs.m_redo.rseg = trx_assign_rseg_low();
 
 	ut_ad(trx->rsegs.m_redo.rseg != 0);
 
diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc
index 92e18c1c372..3eab3733f8f 100644
--- a/storage/innobase/trx/trx0undo.cc
+++ b/storage/innobase/trx/trx0undo.cc
@@ -1027,7 +1027,7 @@ void
 trx_undo_truncate_end(trx_undo_t* undo, undo_no_t limit, bool is_temp)
 {
 	ut_ad(mutex_own(&undo->rseg->mutex));
-	ut_ad(is_temp == trx_sys_is_noredo_rseg_slot(undo->rseg->id));
+	ut_ad(is_temp == !undo->rseg->is_persistent());
 
 	for (;;) {
 		mtr_t		mtr;
@@ -1102,7 +1102,7 @@ trx_undo_truncate_start(
 loop:
 	mtr_start(&mtr);
 
-	if (trx_sys_is_noredo_rseg_slot(rseg->id)) {
+	if (!rseg->is_persistent()) {
 		mtr.set_log_mode(MTR_LOG_NO_REDO);
 	}
 
@@ -1856,7 +1856,7 @@ void
 trx_undo_commit_cleanup(trx_undo_t* undo, bool is_temp)
 {
 	trx_rseg_t*	rseg	= undo->rseg;
-	ut_ad(is_temp == trx_sys_is_noredo_rseg_slot(rseg->id));
+	ut_ad(is_temp == !rseg->is_persistent());
 
 	mutex_enter(&rseg->mutex);
 


More information about the commits mailing list