mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
Merge 10.2 into bb-10.2-mariarocks
This commit is contained in:
Submodule libmariadb updated: e9868bfce0...d138735629
@@ -140,3 +140,7 @@ create table t1 (a int, b int, check(a>0));
|
||||
alter table t1 drop column a;
|
||||
ERROR 42S22: Unknown column 'a' in 'CHECK'
|
||||
drop table t1;
|
||||
create table t1 (a int check (@b in (select user from mysql.user)));
|
||||
ERROR HY000: Function or expression 'select ...' cannot be used in the CHECK clause of `a`
|
||||
create table t1 (a int check (a > @b));
|
||||
ERROR HY000: Function or expression '@b' cannot be used in the CHECK clause of `a`
|
||||
|
@@ -121,3 +121,12 @@ a
|
||||
2
|
||||
#cleanup
|
||||
DROP TABLE t1, pid_table;
|
||||
#
|
||||
# MDEV-12416 OOM in create_virtual_tmp_table() makes the server crash
|
||||
#
|
||||
CREATE FUNCTION f1(a INT) RETURNS INT RETURN a;
|
||||
SET SESSION debug_dbug="+d,simulate_create_virtual_tmp_table_out_of_memory";
|
||||
SELECT f1(1);
|
||||
Got one of the listed errors
|
||||
DROP FUNCTION f1;
|
||||
SET SESSION debug_dbug=DEFAULT;
|
||||
|
@@ -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 1 /Expected to open 3 undo tablespaces but was able to find only 1 undo tablespaces/ in mysqld.1.err
|
||||
FOUND 1 /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 1 /Expected to open 3 undo tablespaces but was able to find only 0 undo tablespaces/ in mysqld.1.err
|
||||
FOUND 1 /InnoDB: Unable to open undo tablespace.*undo001/ in mysqld.1.err
|
||||
bak_ib_logfile0
|
||||
bak_ib_logfile1
|
||||
bak_ib_logfile2
|
||||
|
@@ -40,7 +40,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;
|
||||
@@ -171,7 +171,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
|
||||
@@ -183,7 +183,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
|
||||
|
@@ -1 +1 @@
|
||||
cmp_per_index: MDEV-11629
|
||||
|
||||
|
@@ -39,13 +39,13 @@ BEGIN;
|
||||
COMMIT;
|
||||
ALTER TABLE t DROP INDEX c;
|
||||
GRANT USAGE ON *.* TO 'tuser01'@'localhost' IDENTIFIED BY 'cDJvI9s_Uq';
|
||||
Warnings:
|
||||
Level Warning
|
||||
Code 1287
|
||||
Message Using GRANT for creating new user is deprecated and will be removed in future release. Create new user with CREATE USER statement.
|
||||
FLUSH PRIVILEGES;
|
||||
connect con1,localhost,tuser01,cDJvI9s_Uq,;
|
||||
connection con1;
|
||||
SELECT * FROM information_schema.innodb_cmp_per_index;
|
||||
ERROR 42000: Access denied; you need (at least one of) the PROCESS privilege(s) for this operation
|
||||
connection default;
|
||||
disconnect con1;
|
||||
DROP USER 'tuser01'@'localhost';
|
||||
SELECT
|
||||
database_name,
|
||||
@@ -70,7 +70,6 @@ index_name PRIMARY
|
||||
compress_ops 65
|
||||
compress_ops_ok 65
|
||||
uncompress_ops 0
|
||||
# restart
|
||||
SET GLOBAL innodb_cmp_per_index_enabled=ON;
|
||||
SELECT COUNT(*) FROM t;
|
||||
COUNT(*) 128
|
||||
@@ -86,9 +85,15 @@ FROM information_schema.innodb_cmp_per_index
|
||||
ORDER BY 1, 2, 3;
|
||||
database_name test
|
||||
table_name t
|
||||
index_name b
|
||||
compress_ops 0
|
||||
compress_ops_ok 0
|
||||
uncompress_ops 6
|
||||
database_name test
|
||||
table_name t
|
||||
index_name PRIMARY
|
||||
compress_ops 0
|
||||
compress_ops_ok 0
|
||||
uncompress_ops 9
|
||||
uncompress_ops 5
|
||||
DROP TABLE t;
|
||||
SET GLOBAL innodb_cmp_per_index_enabled=default;
|
||||
|
2
mysql-test/suite/innodb_zip/t/cmp_per_index.opt
Normal file
2
mysql-test/suite/innodb_zip/t/cmp_per_index.opt
Normal file
@@ -0,0 +1,2 @@
|
||||
--innodb_log_compressed_pages=on
|
||||
--innodb_cmp_per_index_reset
|
@@ -40,12 +40,6 @@ connection default;
|
||||
select * from t1;
|
||||
a b c d e
|
||||
2010-10-10 10:10:10 1 0 0 NULL
|
||||
Warnings:
|
||||
Warning 1292 Incorrect datetime value: '1'
|
||||
Warning 1292 Incorrect datetime value: '2'
|
||||
Warning 1292 Incorrect datetime value: '1'
|
||||
Warning 1292 Incorrect datetime value: '1'
|
||||
Warning 1292 Incorrect datetime value: '2'
|
||||
drop table t1;
|
||||
connect con1, localhost, root;
|
||||
create table t1 (a datetime,
|
||||
|
@@ -16,11 +16,15 @@ create table t1 (a datetime,
|
||||
);
|
||||
show create table t1;
|
||||
connect con1, localhost, root;
|
||||
disable_warnings;
|
||||
insert t1 (a) values ('2010-10-10 10:10:10');
|
||||
enable_warnings;
|
||||
select * from t1;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
disable_warnings;
|
||||
select * from t1;
|
||||
enable_warnings;
|
||||
drop table t1;
|
||||
|
||||
connect con1, localhost, root;
|
||||
|
@@ -86,3 +86,11 @@ create table t1 (a int, b int, check(a>0));
|
||||
--error ER_BAD_FIELD_ERROR
|
||||
alter table t1 drop column a;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# MDEV-12421 Check constraint with query crashes server and renders DB unusable
|
||||
#
|
||||
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||
create table t1 (a int check (@b in (select user from mysql.user)));
|
||||
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||
create table t1 (a int check (a > @b));
|
||||
|
@@ -148,3 +148,17 @@ SELECT a FROM t1 ORDER BY rand(1);
|
||||
|
||||
--echo #cleanup
|
||||
DROP TABLE t1, pid_table;
|
||||
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-12416 OOM in create_virtual_tmp_table() makes the server crash
|
||||
--echo #
|
||||
|
||||
CREATE FUNCTION f1(a INT) RETURNS INT RETURN a;
|
||||
SET SESSION debug_dbug="+d,simulate_create_virtual_tmp_table_out_of_memory";
|
||||
# May fail with either ER_OUT_OF_RESOURCES or EE_OUTOFMEMORY
|
||||
--error ER_OUT_OF_RESOURCES, 5
|
||||
SELECT f1(1);
|
||||
DROP FUNCTION f1;
|
||||
SET SESSION debug_dbug=DEFAULT;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
--source include/not_valgrind.inc
|
||||
--disable_ps_protocol
|
||||
--source include/no_protocol.inc
|
||||
|
||||
SET GLOBAL net_write_timeout = 900;
|
||||
|
||||
|
@@ -137,8 +137,8 @@ ELSE()
|
||||
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/aws_sdk_cpp/include)
|
||||
ENDIF()
|
||||
|
||||
MYSQL_ADD_PLUGIN(aws_key_management aws_key_management_plugin.cc
|
||||
COMPONENT aws-key-management)
|
||||
ADD_DEFINITIONS(${SSL_DEFINES}) # Need to know whether openssl should be initialized
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX11_FLAGS}")
|
||||
TARGET_LINK_LIBRARIES(aws_key_management ${AWS_SDK_LIBS})
|
||||
MYSQL_ADD_PLUGIN(aws_key_management aws_key_management_plugin.cc
|
||||
LINK_LIBRARIES ${AWS_SDK_LIBS}
|
||||
COMPONENT aws-key-management)
|
||||
|
@@ -1993,7 +1993,7 @@ class Virtual_tmp_table: public TABLE
|
||||
|
||||
This is needed to avoid memory leaks, as some fields can be BLOB
|
||||
variants and thus can have String onboard. Strings must be destructed
|
||||
as they store data not the heap (not on MEM_ROOT).
|
||||
as they store data on the heap (not on MEM_ROOT).
|
||||
*/
|
||||
void destruct_fields()
|
||||
{
|
||||
@@ -2025,6 +2025,7 @@ public:
|
||||
@param thd - Current thread.
|
||||
*/
|
||||
static void *operator new(size_t size, THD *thd) throw();
|
||||
static void operator delete(void *ptr, size_t size) { TRASH(ptr, size); }
|
||||
|
||||
Virtual_tmp_table(THD *thd)
|
||||
{
|
||||
@@ -2035,7 +2036,8 @@ public:
|
||||
|
||||
~Virtual_tmp_table()
|
||||
{
|
||||
destruct_fields();
|
||||
if (s)
|
||||
destruct_fields();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2120,6 +2122,17 @@ create_virtual_tmp_table(THD *thd, List<Column_definition> &field_list)
|
||||
Virtual_tmp_table *table;
|
||||
if (!(table= new(thd) Virtual_tmp_table(thd)))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
If "simulate_create_virtual_tmp_table_out_of_memory" debug option
|
||||
is enabled, we now enable "simulate_out_of_memory". This effectively
|
||||
makes table->init() fail on OOM inside multi_alloc_root().
|
||||
This is done to test that ~Virtual_tmp_table() called from the "delete"
|
||||
below correcly handles OOM.
|
||||
*/
|
||||
DBUG_EXECUTE_IF("simulate_create_virtual_tmp_table_out_of_memory",
|
||||
DBUG_SET("+d,simulate_out_of_memory"););
|
||||
|
||||
if (table->init(field_list.elements) ||
|
||||
table->add(field_list) ||
|
||||
table->open())
|
||||
|
@@ -4667,7 +4667,7 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table,
|
||||
table_list.view= (LEX*) share->is_view;
|
||||
res= schema_table->process_table(thd, &table_list, table,
|
||||
res, db_name, table_name);
|
||||
free_root(&tbl.mem_root, MYF(0));
|
||||
closefrm(&tbl);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -6013,8 +6013,8 @@ field_list_item:
|
||||
;
|
||||
|
||||
column_def:
|
||||
field_spec opt_check_constraint
|
||||
{ $$= $1; $$->check_constraint= $2; }
|
||||
field_spec
|
||||
{ $$= $1; }
|
||||
| field_spec references
|
||||
{ $$= $1; }
|
||||
;
|
||||
@@ -6152,11 +6152,13 @@ field_spec:
|
||||
lex->init_last_field(f, $1.str, NULL);
|
||||
$<create_field>$= f;
|
||||
}
|
||||
field_type_or_serial
|
||||
field_type_or_serial opt_check_constraint
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
$$= $<create_field>2;
|
||||
|
||||
$$->check_constraint= $4;
|
||||
|
||||
if ($$->check(thd))
|
||||
MYSQL_YYABORT;
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@@ -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;
|
||||
|
@@ -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.
|
||||
@param[in] id rollback segment id
|
||||
@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.
|
||||
@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 */
|
||||
|
@@ -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.
|
||||
@return slot index or ULINT_UNDEFINED if not found */
|
||||
/** @return an unallocated rollback segment slot in the TRX_SYS header
|
||||
@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 */
|
||||
@@ -160,14 +153,6 @@ trx_sys_get_max_trx_id(void);
|
||||
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
|
||||
@@ -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
|
||||
@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.
|
||||
@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 */
|
||||
@@ -556,13 +535,15 @@ struct trx_sys_t {
|
||||
transactions which exist or existed */
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
char pad1[64]; /*!< To avoid false sharing */
|
||||
/** Avoid false sharing */
|
||||
const char pad1[CACHE_LINE_SIZE];
|
||||
trx_ut_list_t rw_trx_list; /*!< List of active and committed in
|
||||
memory read-write transactions, sorted
|
||||
on trx id, biggest first. Recovered
|
||||
transactions are always on this list. */
|
||||
|
||||
char pad2[64]; /*!< To avoid false sharing */
|
||||
/** Avoid false sharing */
|
||||
const char pad2[CACHE_LINE_SIZE];
|
||||
trx_ut_list_t mysql_trx_list; /*!< List of transactions created
|
||||
for MySQL. All user transactions are
|
||||
on mysql_trx_list. The rw_trx_list
|
||||
@@ -582,7 +563,13 @@ struct trx_sys_t {
|
||||
to ensure right order of removal and
|
||||
consistent snapshot. */
|
||||
|
||||
char pad3[64]; /*!< To avoid false sharing */
|
||||
/** Avoid false sharing */
|
||||
const char pad3[CACHE_LINE_SIZE];
|
||||
/** Temporary rollback segments */
|
||||
trx_rseg_t* temp_rsegs[TRX_SYS_N_RSEGS];
|
||||
/** Avoid false sharing */
|
||||
const char pad4[CACHE_LINE_SIZE];
|
||||
|
||||
trx_rseg_t* rseg_array[TRX_SYS_N_RSEGS];
|
||||
/*!< Pointer array to rollback
|
||||
segments; NULL if slot not in use;
|
||||
|
@@ -191,18 +191,6 @@ trx_write_trx_id(
|
||||
mach_write_to_6(ptr, 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
|
||||
|
@@ -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();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -741,10 +741,11 @@ skip_secondaries:
|
||||
&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);
|
||||
|
||||
|
@@ -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;
|
||||
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 = 0;
|
||||
ulint srv_available_undo_logs = 0;
|
||||
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 = 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;
|
||||
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. */
|
||||
|
@@ -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));
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
@param[in] hdr_addr file address of log_hdr
|
||||
@param[in] noredo skip redo logging. */
|
||||
@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.
|
||||
@param[in,out] rseg rollback segment
|
||||
@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 @@ loop:
|
||||
|
||||
/* 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 @@ loop:
|
||||
}
|
||||
|
||||
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
|
||||
|
@@ -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 @@ err_exit:
|
||||
|
||||
/*============== 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.
|
||||
@return own: copy of the record */
|
||||
/** Copy an undo record to heap.
|
||||
@param[in] roll_ptr roll pointer to a record that exists
|
||||
@param[in] is_temp whether this is a temporary table
|
||||
@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
|
||||
@param[in] is_temp whether this is a temporary table
|
||||
@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
|
||||
@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. */
|
||||
|
@@ -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
|
||||
@param[in] page_no page number of the segment header
|
||||
@param[in,out] mtr mini-transaction */
|
||||
@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);
|
||||
}
|
||||
|
||||
rseg_header = trx_rsegf_get_new(space, page_no, mtr);
|
||||
/** Restore the state of a persistent rollback segment.
|
||||
@param[in,out] rseg persistent rollback segment
|
||||
@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(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.
|
||||
@return pointer to new rollback segment if create successful */
|
||||
/** Create a persistent rollback segment.
|
||||
@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();
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
@@ -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.
|
||||
@return slot index or ULINT_UNDEFINED if not found */
|
||||
/** @return an unallocated rollback segment slot in the TRX_SYS header
|
||||
@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;
|
||||
trx_sysf_t* sys_header = trx_sysf_get(mtr);
|
||||
|
||||
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);
|
||||
|
||||
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.
|
||||
@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.
|
||||
@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. */
|
||||
/** Create the rollback segments.
|
||||
@return whether the creation succeeded */
|
||||
bool
|
||||
trx_sys_create_rsegs()
|
||||
{
|
||||
ulint n_created = 0;
|
||||
/* srv_available_undo_logs reflects the number of persistent
|
||||
rollback segments that have been initialized in the
|
||||
transaction system header page.
|
||||
|
||||
/* 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.
|
||||
@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. */
|
||||
{
|
||||
mtr_t mtr;
|
||||
ulint n_used;
|
||||
ulint n_noredo_created;
|
||||
|
||||
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;
|
||||
/* The first persistent rollback segment is always initialized
|
||||
in the system tablespace. */
|
||||
ut_a(srv_available_undo_logs > 0);
|
||||
|
||||
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 {
|
||||
n_redo_active = n_rsegs - n_tmp_rsegs;
|
||||
}
|
||||
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;
|
||||
|
||||
/* 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. */
|
||||
|
||||
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 (!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);
|
||||
|
@@ -1090,43 +1090,34 @@ trx_lists_init_at_db_start()
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Get next redo rollback segment. (Segment are assigned in round-robin fashion).
|
||||
@return assigned rollback segment instance */
|
||||
/** Assign a persistent rollback segment in a round-robin fashion,
|
||||
evenly distributed between 0 and innodb_undo_logs-1
|
||||
@return persistent rollback segment
|
||||
@retval NULL if innodb_read_only */
|
||||
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 */
|
||||
trx_assign_rseg_low()
|
||||
{
|
||||
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;
|
||||
}
|
||||
if (srv_read_only_mode) {
|
||||
ut_ad(srv_undo_logs == ULONG_UNDEFINED);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* The first slot is always assigned to the system tablespace. */
|
||||
ut_ad(trx_sys->rseg_array[0]->space == TRX_SYS_SPACE);
|
||||
|
||||
/* Choose a rollback segment evenly distributed between 0 and
|
||||
innodb_undo_logs-1 in a round-robin fashion, skipping those
|
||||
undo tablespaces that are scheduled for truncation.
|
||||
|
||||
Because rseg_slot is not protected by atomics or any mutex, race
|
||||
conditions are possible, meaning that multiple transactions
|
||||
that start modifications concurrently will write their undo
|
||||
log to the same rollback segment. */
|
||||
static ulong rseg_slot;
|
||||
ulint slot = rseg_slot++ % srv_undo_logs;
|
||||
trx_rseg_t* rseg;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
ulint start_scan_slot = slot;
|
||||
bool look_for_rollover = false;
|
||||
@@ -1134,8 +1125,7 @@ get_next_redo_rseg(
|
||||
|
||||
bool allocated = false;
|
||||
|
||||
while (!allocated) {
|
||||
|
||||
do {
|
||||
for (;;) {
|
||||
rseg = trx_sys->rseg_array[slot];
|
||||
|
||||
@@ -1148,37 +1138,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 +1175,43 @@ 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.
|
||||
@return assigned rollback segment instance */
|
||||
static
|
||||
/** Assign a rollback segment for modifying temporary tables.
|
||||
@return the assigned rollback segment */
|
||||
trx_rseg_t*
|
||||
get_next_noredo_rseg(
|
||||
/*=================*/
|
||||
ulong max_undo_logs) /*!< in: maximum number of UNDO logs to use */
|
||||
trx_t::assign_temp_rseg()
|
||||
{
|
||||
trx_rseg_t* rseg;
|
||||
static ulint noredo_rseg_slot = 1;
|
||||
ulint slot = 0;
|
||||
ut_ad(!rsegs.m_noredo.rseg);
|
||||
ut_ad(!trx_is_autocommit_non_locking(this));
|
||||
compile_time_assert(ut_is_2pow(TRX_SYS_N_RSEGS));
|
||||
|
||||
slot = noredo_rseg_slot++;
|
||||
slot = slot % max_undo_logs;
|
||||
while (!trx_sys_is_noredo_rseg_slot(slot)) {
|
||||
slot = (slot + 1) % max_undo_logs;
|
||||
}
|
||||
/* Choose a temporary rollback segment between 0 and 127
|
||||
in a round-robin fashion. Because rseg_slot is not protected by
|
||||
atomics or any mutex, race conditions are possible, meaning that
|
||||
multiple transactions that start modifications concurrently
|
||||
will write their undo log to the same rollback segment. */
|
||||
static ulong rseg_slot;
|
||||
trx_rseg_t* rseg = trx_sys->temp_rsegs[
|
||||
rseg_slot++ & (TRX_SYS_N_RSEGS - 1)];
|
||||
ut_ad(!rseg->is_persistent());
|
||||
rsegs.m_noredo.rseg = rseg;
|
||||
|
||||
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.
|
||||
@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. */
|
||||
{
|
||||
if (srv_read_only_mode) {
|
||||
ut_a(max_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);
|
||||
|
||||
/* 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;
|
||||
|
||||
case TRX_RSEG_TYPE_NOREDO:
|
||||
rseg = get_next_noredo_rseg(srv_tmp_undo_logs + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
return(rseg);
|
||||
}
|
||||
|
||||
/****************************************************************//**
|
||||
Assign a transaction temp-tablespace bounded rollback-segment. */
|
||||
void
|
||||
trx_assign_rseg(
|
||||
/*============*/
|
||||
trx_t* trx) /*!< transaction that involves write
|
||||
to temp-table. */
|
||||
{
|
||||
ut_a(trx->rsegs.m_noredo.rseg == 0);
|
||||
ut_a(!trx_is_autocommit_non_locking(trx));
|
||||
|
||||
trx->rsegs.m_noredo.rseg = trx_assign_rseg_low(
|
||||
srv_undo_logs, srv_undo_tablespaces, TRX_RSEG_TYPE_NOREDO);
|
||||
|
||||
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 +1286,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 +2865,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 +3010,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);
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user