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;
|
alter table t1 drop column a;
|
||||||
ERROR 42S22: Unknown column 'a' in 'CHECK'
|
ERROR 42S22: Unknown column 'a' in 'CHECK'
|
||||||
drop table t1;
|
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
|
2
|
||||||
#cleanup
|
#cleanup
|
||||||
DROP TABLE t1, pid_table;
|
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'
|
WHERE engine = 'innodb'
|
||||||
AND support IN ('YES', 'DEFAULT', 'ENABLED');
|
AND support IN ('YES', 'DEFAULT', 'ENABLED');
|
||||||
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
|
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_logfile0
|
||||||
bak_ib_logfile1
|
bak_ib_logfile1
|
||||||
bak_ib_logfile2
|
bak_ib_logfile2
|
||||||
@@ -244,7 +244,7 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES
|
|||||||
WHERE engine = 'innodb'
|
WHERE engine = 'innodb'
|
||||||
AND support IN ('YES', 'DEFAULT', 'ENABLED');
|
AND support IN ('YES', 'DEFAULT', 'ENABLED');
|
||||||
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
|
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_logfile0
|
||||||
bak_ib_logfile1
|
bak_ib_logfile1
|
||||||
bak_ib_logfile2
|
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
|
--let $ibp=$ibp --innodb-data-file-path=ibdata1:16M;ibdata2:10M:autoextend
|
||||||
|
|
||||||
--echo # Start mysqld without the possibility to create innodb_undo_tablespaces
|
--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
|
--mkdir $bugdir/undo002
|
||||||
--source include/restart_mysqld.inc
|
--source include/restart_mysqld.inc
|
||||||
eval $check_no_innodb;
|
eval $check_no_innodb;
|
||||||
@@ -171,7 +171,7 @@ let SEARCH_PATTERN=undo tablespace .*undo003.* exists\. Creating system tablespa
|
|||||||
--source include/start_mysqld.inc
|
--source include/start_mysqld.inc
|
||||||
eval $check_no_innodb;
|
eval $check_no_innodb;
|
||||||
--source include/shutdown_mysqld.inc
|
--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
|
--source include/search_pattern_in_file.inc
|
||||||
# clean up & Restore
|
# clean up & Restore
|
||||||
--source ../include/log_file_cleanup.inc
|
--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
|
--source include/start_mysqld.inc
|
||||||
eval $check_no_innodb;
|
eval $check_no_innodb;
|
||||||
--source include/shutdown_mysqld.inc
|
--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
|
--source include/search_pattern_in_file.inc
|
||||||
|
|
||||||
# clean up & Restore
|
# clean up & Restore
|
||||||
|
@@ -1 +1 @@
|
|||||||
cmp_per_index: MDEV-11629
|
|
||||||
|
@@ -39,13 +39,13 @@ BEGIN;
|
|||||||
COMMIT;
|
COMMIT;
|
||||||
ALTER TABLE t DROP INDEX c;
|
ALTER TABLE t DROP INDEX c;
|
||||||
GRANT USAGE ON *.* TO 'tuser01'@'localhost' IDENTIFIED BY 'cDJvI9s_Uq';
|
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;
|
FLUSH PRIVILEGES;
|
||||||
|
connect con1,localhost,tuser01,cDJvI9s_Uq,;
|
||||||
|
connection con1;
|
||||||
SELECT * FROM information_schema.innodb_cmp_per_index;
|
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
|
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';
|
DROP USER 'tuser01'@'localhost';
|
||||||
SELECT
|
SELECT
|
||||||
database_name,
|
database_name,
|
||||||
@@ -70,7 +70,6 @@ index_name PRIMARY
|
|||||||
compress_ops 65
|
compress_ops 65
|
||||||
compress_ops_ok 65
|
compress_ops_ok 65
|
||||||
uncompress_ops 0
|
uncompress_ops 0
|
||||||
# restart
|
|
||||||
SET GLOBAL innodb_cmp_per_index_enabled=ON;
|
SET GLOBAL innodb_cmp_per_index_enabled=ON;
|
||||||
SELECT COUNT(*) FROM t;
|
SELECT COUNT(*) FROM t;
|
||||||
COUNT(*) 128
|
COUNT(*) 128
|
||||||
@@ -86,9 +85,15 @@ FROM information_schema.innodb_cmp_per_index
|
|||||||
ORDER BY 1, 2, 3;
|
ORDER BY 1, 2, 3;
|
||||||
database_name test
|
database_name test
|
||||||
table_name t
|
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
|
index_name PRIMARY
|
||||||
compress_ops 0
|
compress_ops 0
|
||||||
compress_ops_ok 0
|
compress_ops_ok 0
|
||||||
uncompress_ops 9
|
uncompress_ops 5
|
||||||
DROP TABLE t;
|
DROP TABLE t;
|
||||||
SET GLOBAL innodb_cmp_per_index_enabled=default;
|
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;
|
select * from t1;
|
||||||
a b c d e
|
a b c d e
|
||||||
2010-10-10 10:10:10 1 0 0 NULL
|
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;
|
drop table t1;
|
||||||
connect con1, localhost, root;
|
connect con1, localhost, root;
|
||||||
create table t1 (a datetime,
|
create table t1 (a datetime,
|
||||||
|
@@ -16,11 +16,15 @@ create table t1 (a datetime,
|
|||||||
);
|
);
|
||||||
show create table t1;
|
show create table t1;
|
||||||
connect con1, localhost, root;
|
connect con1, localhost, root;
|
||||||
|
disable_warnings;
|
||||||
insert t1 (a) values ('2010-10-10 10:10:10');
|
insert t1 (a) values ('2010-10-10 10:10:10');
|
||||||
|
enable_warnings;
|
||||||
select * from t1;
|
select * from t1;
|
||||||
disconnect con1;
|
disconnect con1;
|
||||||
connection default;
|
connection default;
|
||||||
|
disable_warnings;
|
||||||
select * from t1;
|
select * from t1;
|
||||||
|
enable_warnings;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
connect con1, localhost, root;
|
connect con1, localhost, root;
|
||||||
|
@@ -86,3 +86,11 @@ create table t1 (a int, b int, check(a>0));
|
|||||||
--error ER_BAD_FIELD_ERROR
|
--error ER_BAD_FIELD_ERROR
|
||||||
alter table t1 drop column a;
|
alter table t1 drop column a;
|
||||||
drop table t1;
|
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
|
--echo #cleanup
|
||||||
DROP TABLE t1, pid_table;
|
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
|
--source include/not_valgrind.inc
|
||||||
--disable_ps_protocol
|
--source include/no_protocol.inc
|
||||||
|
|
||||||
SET GLOBAL net_write_timeout = 900;
|
SET GLOBAL net_write_timeout = 900;
|
||||||
|
|
||||||
|
@@ -137,8 +137,8 @@ ELSE()
|
|||||||
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/aws_sdk_cpp/include)
|
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/aws_sdk_cpp/include)
|
||||||
ENDIF()
|
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
|
ADD_DEFINITIONS(${SSL_DEFINES}) # Need to know whether openssl should be initialized
|
||||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX11_FLAGS}")
|
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
|
This is needed to avoid memory leaks, as some fields can be BLOB
|
||||||
variants and thus can have String onboard. Strings must be destructed
|
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()
|
void destruct_fields()
|
||||||
{
|
{
|
||||||
@@ -2025,6 +2025,7 @@ public:
|
|||||||
@param thd - Current thread.
|
@param thd - Current thread.
|
||||||
*/
|
*/
|
||||||
static void *operator new(size_t size, THD *thd) throw();
|
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)
|
Virtual_tmp_table(THD *thd)
|
||||||
{
|
{
|
||||||
@@ -2035,7 +2036,8 @@ public:
|
|||||||
|
|
||||||
~Virtual_tmp_table()
|
~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;
|
Virtual_tmp_table *table;
|
||||||
if (!(table= new(thd) Virtual_tmp_table(thd)))
|
if (!(table= new(thd) Virtual_tmp_table(thd)))
|
||||||
return NULL;
|
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) ||
|
if (table->init(field_list.elements) ||
|
||||||
table->add(field_list) ||
|
table->add(field_list) ||
|
||||||
table->open())
|
table->open())
|
||||||
|
@@ -4667,7 +4667,7 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table,
|
|||||||
table_list.view= (LEX*) share->is_view;
|
table_list.view= (LEX*) share->is_view;
|
||||||
res= schema_table->process_table(thd, &table_list, table,
|
res= schema_table->process_table(thd, &table_list, table,
|
||||||
res, db_name, table_name);
|
res, db_name, table_name);
|
||||||
free_root(&tbl.mem_root, MYF(0));
|
closefrm(&tbl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -6013,8 +6013,8 @@ field_list_item:
|
|||||||
;
|
;
|
||||||
|
|
||||||
column_def:
|
column_def:
|
||||||
field_spec opt_check_constraint
|
field_spec
|
||||||
{ $$= $1; $$->check_constraint= $2; }
|
{ $$= $1; }
|
||||||
| field_spec references
|
| field_spec references
|
||||||
{ $$= $1; }
|
{ $$= $1; }
|
||||||
;
|
;
|
||||||
@@ -6152,11 +6152,13 @@ field_spec:
|
|||||||
lex->init_last_field(f, $1.str, NULL);
|
lex->init_last_field(f, $1.str, NULL);
|
||||||
$<create_field>$= f;
|
$<create_field>$= f;
|
||||||
}
|
}
|
||||||
field_type_or_serial
|
field_type_or_serial opt_check_constraint
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
$$= $<create_field>2;
|
$$= $<create_field>2;
|
||||||
|
|
||||||
|
$$->check_constraint= $4;
|
||||||
|
|
||||||
if ($$->check(thd))
|
if ($$->check(thd))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
|
|
||||||
|
@@ -22140,7 +22140,7 @@ innobase_undo_logs_init_default_max()
|
|||||||
{
|
{
|
||||||
MYSQL_SYSVAR_NAME(undo_logs).max_val
|
MYSQL_SYSVAR_NAME(undo_logs).max_val
|
||||||
= MYSQL_SYSVAR_NAME(undo_logs).def_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. */
|
/* Enables or disables this prefix optimization. Disabled by default. */
|
||||||
extern my_bool srv_prefix_index_cluster_optimization;
|
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. */
|
/** Default size of UNDO tablespace while it is created new. */
|
||||||
extern const ulint SRV_UNDO_TABLESPACE_SIZE_IN_PAGES;
|
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 ibool srv_priority_boost;
|
||||||
|
|
||||||
extern ulint srv_truncated_status_writes;
|
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
|
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
|
||||||
extern my_bool srv_ibuf_disable_background_merge;
|
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 */
|
trx_rsegf_t* rsegf, /*!< in: rollback segment header */
|
||||||
mtr_t* mtr); /*!< in: mtr */
|
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.
|
/** Creates a rollback segment header.
|
||||||
This function is called only when a new rollback segment is created in
|
This function is called only when a new rollback segment is created in
|
||||||
@@ -119,14 +109,14 @@ trx_rseg_array_init();
|
|||||||
void
|
void
|
||||||
trx_rseg_mem_free(trx_rseg_t* rseg);
|
trx_rseg_mem_free(trx_rseg_t* rseg);
|
||||||
|
|
||||||
/*********************************************************************
|
/** Create a persistent rollback segment.
|
||||||
Creates a rollback segment. */
|
@param[in] space_id system or undo tablespace id */
|
||||||
trx_rseg_t*
|
trx_rseg_t*
|
||||||
trx_rseg_create(
|
trx_rseg_create(ulint space_id);
|
||||||
/*============*/
|
|
||||||
ulint space_id, /*!< in: id of UNDO tablespace */
|
/** Create the temporary rollback segments. */
|
||||||
ulint nth_free_slot); /*!< in: allocate nth free slot.
|
void
|
||||||
0 means next free slots. */
|
trx_temp_rseg_create();
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
Get the number of unique rollback tablespaces in use except space id 0.
|
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
|
/** If true, then skip allocating this rseg as it reside in
|
||||||
UNDO-tablespace marked for truncate. */
|
UNDO-tablespace marked for truncate. */
|
||||||
bool skip_allocation;
|
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 */
|
/* Undo log segment slot in a rollback segment header */
|
||||||
|
@@ -75,17 +75,10 @@ Creates and initializes the transaction system at the database creation. */
|
|||||||
void
|
void
|
||||||
trx_sys_create_sys_pages(void);
|
trx_sys_create_sys_pages(void);
|
||||||
/*==========================*/
|
/*==========================*/
|
||||||
/****************************************************************//**
|
/** @return an unallocated rollback segment slot in the TRX_SYS header
|
||||||
Looks for a free slot for a rollback segment in the trx system file copy.
|
@retval ULINT_UNDEFINED if not found */
|
||||||
@return slot index or ULINT_UNDEFINED if not found */
|
|
||||||
ulint
|
ulint
|
||||||
trx_sysf_rseg_find_free(
|
trx_sysf_rseg_find_free(mtr_t* mtr);
|
||||||
/*====================*/
|
|
||||||
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. */
|
|
||||||
/**********************************************************************//**
|
/**********************************************************************//**
|
||||||
Gets a pointer to the transaction system file copy and x-locks its page.
|
Gets a pointer to the transaction system file copy and x-locks its page.
|
||||||
@return pointer to system file copy, page x-locked */
|
@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;
|
extern uint trx_rseg_n_slots_debug;
|
||||||
#endif
|
#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
|
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
|
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 */
|
ulint format_id, /*!< in: file format id */
|
||||||
const char** name); /*!< out: max file format name or
|
const char** name); /*!< out: max file format name or
|
||||||
NULL if not needed. */
|
NULL if not needed. */
|
||||||
/*********************************************************************
|
/** Create the rollback segments.
|
||||||
Creates the rollback segments
|
@return whether the creation succeeded */
|
||||||
@return number of rollback segments that are active. */
|
bool
|
||||||
ulint
|
trx_sys_create_rsegs();
|
||||||
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. */
|
|
||||||
/*****************************************************************//**
|
/*****************************************************************//**
|
||||||
Get the number of transaction in the system, independent of their state.
|
Get the number of transaction in the system, independent of their state.
|
||||||
@return count of transactions in trx_sys_t::trx_list */
|
@return count of transactions in trx_sys_t::trx_list */
|
||||||
@@ -556,13 +535,15 @@ struct trx_sys_t {
|
|||||||
transactions which exist or existed */
|
transactions which exist or existed */
|
||||||
#endif /* UNIV_DEBUG */
|
#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
|
trx_ut_list_t rw_trx_list; /*!< List of active and committed in
|
||||||
memory read-write transactions, sorted
|
memory read-write transactions, sorted
|
||||||
on trx id, biggest first. Recovered
|
on trx id, biggest first. Recovered
|
||||||
transactions are always on this list. */
|
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
|
trx_ut_list_t mysql_trx_list; /*!< List of transactions created
|
||||||
for MySQL. All user transactions are
|
for MySQL. All user transactions are
|
||||||
on mysql_trx_list. The rw_trx_list
|
on mysql_trx_list. The rw_trx_list
|
||||||
@@ -582,7 +563,13 @@ struct trx_sys_t {
|
|||||||
to ensure right order of removal and
|
to ensure right order of removal and
|
||||||
consistent snapshot. */
|
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];
|
trx_rseg_t* rseg_array[TRX_SYS_N_RSEGS];
|
||||||
/*!< Pointer array to rollback
|
/*!< Pointer array to rollback
|
||||||
segments; NULL if slot not in use;
|
segments; NULL if slot not in use;
|
||||||
|
@@ -191,18 +191,6 @@ trx_write_trx_id(
|
|||||||
mach_write_to_6(ptr, 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
|
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
|
some future version, this function should be used instead of
|
||||||
|
@@ -507,14 +507,6 @@ trx_id_t
|
|||||||
trx_get_id_for_print(
|
trx_get_id_for_print(
|
||||||
const trx_t* trx);
|
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 */
|
/** Create the trx_t pool */
|
||||||
void
|
void
|
||||||
trx_pool_init();
|
trx_pool_init();
|
||||||
@@ -869,12 +861,6 @@ struct trx_rsegs_t {
|
|||||||
trx_temp_undo_t m_noredo;
|
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 {
|
struct TrxVersion {
|
||||||
TrxVersion(trx_t* trx);
|
TrxVersion(trx_t* trx);
|
||||||
|
|
||||||
@@ -1295,6 +1281,22 @@ struct trx_t {
|
|||||||
{
|
{
|
||||||
return(has_logged_persistent() || rsegs.m_noredo.undo);
|
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,
|
&is_insert, &rseg_id,
|
||||||
&page_no, &offset);
|
&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 != NULL);
|
||||||
ut_a(rseg->id == rseg_id);
|
ut_ad(rseg->id == rseg_id);
|
||||||
|
ut_ad(rseg->is_persistent());
|
||||||
|
|
||||||
mtr_start(&mtr);
|
mtr_start(&mtr);
|
||||||
|
|
||||||
|
@@ -139,10 +139,6 @@ my_bool srv_undo_log_truncate = FALSE;
|
|||||||
/** Maximum size of undo tablespace. */
|
/** Maximum size of undo tablespace. */
|
||||||
unsigned long long srv_max_undo_log_size;
|
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). */
|
/** Default undo tablespace size in UNIV_PAGEs count (10MB). */
|
||||||
const ulint SRV_UNDO_TABLESPACE_SIZE_IN_PAGES =
|
const ulint SRV_UNDO_TABLESPACE_SIZE_IN_PAGES =
|
||||||
((1024 * 1024) * 10) / UNIV_PAGE_SIZE_DEF;
|
((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;
|
uint srv_spin_wait_delay;
|
||||||
ibool srv_priority_boost = TRUE;
|
ibool srv_priority_boost = TRUE;
|
||||||
|
|
||||||
static ulint srv_n_rows_inserted_old = 0;
|
static ulint srv_n_rows_inserted_old;
|
||||||
static ulint srv_n_rows_updated_old = 0;
|
static ulint srv_n_rows_updated_old;
|
||||||
static ulint srv_n_rows_deleted_old = 0;
|
static ulint srv_n_rows_deleted_old;
|
||||||
static ulint srv_n_rows_read_old = 0;
|
static ulint srv_n_rows_read_old;
|
||||||
static ulint srv_n_system_rows_inserted_old = 0;
|
static ulint srv_n_system_rows_inserted_old;
|
||||||
static ulint srv_n_system_rows_updated_old = 0;
|
static ulint srv_n_system_rows_updated_old;
|
||||||
static ulint srv_n_system_rows_deleted_old = 0;
|
static ulint srv_n_system_rows_deleted_old;
|
||||||
static ulint srv_n_system_rows_read_old = 0;
|
static ulint srv_n_system_rows_read_old;
|
||||||
|
|
||||||
ulint srv_truncated_status_writes = 0;
|
ulint srv_truncated_status_writes;
|
||||||
ulint srv_available_undo_logs = 0;
|
/** 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_saved;
|
||||||
UNIV_INTERN ib_uint64_t srv_page_compression_trim_sect512 = 0;
|
UNIV_INTERN ib_uint64_t srv_page_compression_trim_sect512;
|
||||||
UNIV_INTERN ib_uint64_t srv_page_compression_trim_sect4096 = 0;
|
UNIV_INTERN ib_uint64_t srv_page_compression_trim_sect4096;
|
||||||
UNIV_INTERN ib_uint64_t srv_index_pages_written = 0;
|
UNIV_INTERN ib_uint64_t srv_index_pages_written;
|
||||||
UNIV_INTERN ib_uint64_t srv_non_index_pages_written = 0;
|
UNIV_INTERN ib_uint64_t srv_non_index_pages_written;
|
||||||
UNIV_INTERN ib_uint64_t srv_pages_page_compressed = 0;
|
UNIV_INTERN ib_uint64_t srv_pages_page_compressed;
|
||||||
UNIV_INTERN ib_uint64_t srv_page_compressed_trim_op = 0;
|
UNIV_INTERN ib_uint64_t srv_page_compressed_trim_op;
|
||||||
UNIV_INTERN ib_uint64_t srv_page_compressed_trim_op_saved = 0;
|
UNIV_INTERN ib_uint64_t srv_page_compressed_trim_op_saved;
|
||||||
UNIV_INTERN ib_uint64_t srv_index_page_decompressed = 0;
|
UNIV_INTERN ib_uint64_t srv_index_page_decompressed;
|
||||||
|
|
||||||
/* Defragmentation */
|
/* 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_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 uint srv_defragment_fill_factor_n_recs = 20;
|
||||||
UNIV_INTERN double srv_defragment_fill_factor = 0.9;
|
UNIV_INTERN double srv_defragment_fill_factor = 0.9;
|
||||||
UNIV_INTERN uint srv_defragment_frequency =
|
UNIV_INTERN uint srv_defragment_frequency =
|
||||||
SRV_DEFRAGMENT_FREQUENCY_DEFAULT;
|
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
|
/* Set the following to 0 if you want InnoDB to write messages on
|
||||||
stderr on startup/shutdown. */
|
stderr on startup/shutdown. */
|
||||||
|
@@ -804,20 +804,12 @@ srv_check_undo_redo_logs_exists()
|
|||||||
|
|
||||||
undo::undo_spaces_t undo::Truncate::s_fix_up_spaces;
|
undo::undo_spaces_t undo::Truncate::s_fix_up_spaces;
|
||||||
|
|
||||||
/********************************************************************
|
/** Open the configured number of dedicated undo tablespaces.
|
||||||
Opens the configured number of undo tablespaces.
|
@param[in] create_new_db whether the database is being initialized
|
||||||
@return DB_SUCCESS or error code */
|
@return DB_SUCCESS or error code */
|
||||||
static
|
static
|
||||||
dberr_t
|
dberr_t
|
||||||
srv_undo_tablespaces_init(
|
srv_undo_tablespaces_init(bool create_new_db)
|
||||||
/*======================*/
|
|
||||||
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 */
|
|
||||||
{
|
{
|
||||||
ulint i;
|
ulint i;
|
||||||
dberr_t err = DB_SUCCESS;
|
dberr_t err = DB_SUCCESS;
|
||||||
@@ -825,9 +817,9 @@ srv_undo_tablespaces_init(
|
|||||||
ulint n_undo_tablespaces;
|
ulint n_undo_tablespaces;
|
||||||
ulint undo_tablespace_ids[TRX_SYS_N_RSEGS + 1];
|
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));
|
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
|
the location of the undo tablespaces and their space ids this
|
||||||
restriction will/should be lifted. */
|
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];
|
char name[OS_FILE_MAX_PATH];
|
||||||
|
|
||||||
ut_snprintf(
|
ut_snprintf(
|
||||||
@@ -902,7 +894,7 @@ srv_undo_tablespaces_init(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
n_undo_tablespaces = n_conf_tablespaces;
|
n_undo_tablespaces = srv_undo_tablespaces;
|
||||||
|
|
||||||
for (i = 1; i <= n_undo_tablespaces; ++i) {
|
for (i = 1; i <= n_undo_tablespaces; ++i) {
|
||||||
undo_tablespace_ids[i - 1] = i;
|
undo_tablespace_ids[i - 1] = i;
|
||||||
@@ -944,7 +936,7 @@ srv_undo_tablespaces_init(
|
|||||||
|
|
||||||
prev_space_id = undo_tablespace_ids[i];
|
prev_space_id = undo_tablespace_ids[i];
|
||||||
|
|
||||||
++*n_opened;
|
++srv_undo_tablespaces_open;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open any extra unused undo tablespaces. These must be contiguous.
|
/* Open any extra unused undo tablespaces. These must be contiguous.
|
||||||
@@ -968,19 +960,17 @@ srv_undo_tablespaces_init(
|
|||||||
|
|
||||||
++n_undo_tablespaces;
|
++n_undo_tablespaces;
|
||||||
|
|
||||||
++*n_opened;
|
++srv_undo_tablespaces_open;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the user says that there are fewer than what we find we
|
/* If the user says that there are fewer than what we find we
|
||||||
tolerate that discrepancy but not the inverse. Because there could
|
tolerate that discrepancy but not the inverse. Because there could
|
||||||
be unused undo tablespaces for future use. */
|
be unused undo tablespaces for future use. */
|
||||||
|
|
||||||
if (n_conf_tablespaces > n_undo_tablespaces) {
|
if (srv_undo_tablespaces > n_undo_tablespaces) {
|
||||||
ib::error() << "Expected to open " << n_conf_tablespaces
|
ib::error() << "Expected to open innodb_undo_tablespaces="
|
||||||
<< " undo tablespaces but was able to find only "
|
<< srv_undo_tablespaces
|
||||||
<< n_undo_tablespaces << " undo tablespaces. Set the"
|
<< " but was able to find only "
|
||||||
" innodb_undo_tablespaces parameter to the correct"
|
|
||||||
" value and retry. Suggested value is "
|
|
||||||
<< n_undo_tablespaces;
|
<< n_undo_tablespaces;
|
||||||
|
|
||||||
return(err != DB_SUCCESS ? err : DB_ERROR);
|
return(err != DB_SUCCESS ? err : DB_ERROR);
|
||||||
@@ -988,15 +978,13 @@ srv_undo_tablespaces_init(
|
|||||||
} else if (n_undo_tablespaces > 0) {
|
} else if (n_undo_tablespaces > 0) {
|
||||||
|
|
||||||
ib::info() << "Opened " << n_undo_tablespaces
|
ib::info() << "Opened " << n_undo_tablespaces
|
||||||
<< " undo tablespaces";
|
<< " undo tablespaces ("
|
||||||
|
<< srv_undo_tablespaces_active
|
||||||
|
<< " active)";
|
||||||
|
|
||||||
ib::info() << srv_undo_tablespaces_active << " undo tablespaces"
|
if (srv_undo_tablespaces == 0) {
|
||||||
<< " made active";
|
ib::warn() << "innodb_undo_tablespaces=0 disables"
|
||||||
|
" dedicated undo log tablespaces";
|
||||||
if (n_conf_tablespaces == 0) {
|
|
||||||
ib::warn() << "Will use system tablespace for all newly"
|
|
||||||
<< " created rollback-segment as"
|
|
||||||
<< " innodb_undo_tablespaces=0";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2087,10 +2075,7 @@ files_checked:
|
|||||||
fil_open_log_and_system_tablespace_files();
|
fil_open_log_and_system_tablespace_files();
|
||||||
ut_d(fil_space_get(0)->recv_size = srv_sys_space_size_debug);
|
ut_d(fil_space_get(0)->recv_size = srv_sys_space_size_debug);
|
||||||
|
|
||||||
err = srv_undo_tablespaces_init(
|
err = srv_undo_tablespaces_init(create_new_db);
|
||||||
create_new_db,
|
|
||||||
srv_undo_tablespaces,
|
|
||||||
&srv_undo_tablespaces_open);
|
|
||||||
|
|
||||||
/* If the force recovery is set very high then we carry on regardless
|
/* If the force recovery is set very high then we carry on regardless
|
||||||
of all errors. Basically this is fingers crossed mode. */
|
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 > 0);
|
||||||
ut_a(srv_undo_logs <= TRX_SYS_N_RSEGS);
|
ut_a(srv_undo_logs <= TRX_SYS_N_RSEGS);
|
||||||
|
|
||||||
/* The number of rsegs that exist in InnoDB is given by status
|
if (!trx_sys_create_rsegs()) {
|
||||||
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. */
|
|
||||||
return(srv_init_abort(DB_ERROR));
|
return(srv_init_abort(DB_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -327,17 +327,12 @@ trx_purge_remove_log_hdr(
|
|||||||
my_atomic_addlint(&trx_sys->rseg_history_len, -1);
|
my_atomic_addlint(&trx_sys->rseg_history_len, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Frees an undo log segment which is in the history list. Removes the
|
/** Free an undo log segment, and remove the header from the history list.
|
||||||
undo log hdr from the history list.
|
|
||||||
@param[in,out] rseg rollback segment
|
@param[in,out] rseg rollback segment
|
||||||
@param[in] hdr_addr file address of log_hdr
|
@param[in] hdr_addr file address of log_hdr */
|
||||||
@param[in] noredo skip redo logging. */
|
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
trx_purge_free_segment(
|
trx_purge_free_segment(trx_rseg_t* rseg, fil_addr_t hdr_addr)
|
||||||
trx_rseg_t* rseg,
|
|
||||||
fil_addr_t hdr_addr,
|
|
||||||
bool noredo)
|
|
||||||
{
|
{
|
||||||
mtr_t mtr;
|
mtr_t mtr;
|
||||||
trx_rsegf_t* rseg_hdr;
|
trx_rsegf_t* rseg_hdr;
|
||||||
@@ -345,16 +340,12 @@ trx_purge_free_segment(
|
|||||||
trx_usegf_t* seg_hdr;
|
trx_usegf_t* seg_hdr;
|
||||||
ulint seg_size;
|
ulint seg_size;
|
||||||
ulint hist_size;
|
ulint hist_size;
|
||||||
bool marked = noredo;
|
bool marked = false;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
page_t* undo_page;
|
page_t* undo_page;
|
||||||
|
|
||||||
mtr_start(&mtr);
|
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);
|
mutex_enter(&rseg->mutex);
|
||||||
|
|
||||||
@@ -428,14 +419,12 @@ trx_purge_free_segment(
|
|||||||
mtr_commit(&mtr);
|
mtr_commit(&mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************//**
|
/** Remove unnecessary history data from a rollback segment.
|
||||||
Removes unnecessary history data from a rollback segment. */
|
@param[in,out] rseg rollback segment
|
||||||
|
@param[in] limit truncate offset */
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
trx_purge_truncate_rseg_history(
|
trx_purge_truncate_rseg_history(trx_rseg_t* rseg, const purge_iter_t* limit)
|
||||||
/*============================*/
|
|
||||||
trx_rseg_t* rseg, /*!< in: rollback segment */
|
|
||||||
const purge_iter_t* limit) /*!< in: truncate offset */
|
|
||||||
{
|
{
|
||||||
fil_addr_t hdr_addr;
|
fil_addr_t hdr_addr;
|
||||||
fil_addr_t prev_hdr_addr;
|
fil_addr_t prev_hdr_addr;
|
||||||
@@ -445,13 +434,9 @@ trx_purge_truncate_rseg_history(
|
|||||||
trx_usegf_t* seg_hdr;
|
trx_usegf_t* seg_hdr;
|
||||||
mtr_t mtr;
|
mtr_t mtr;
|
||||||
trx_id_t undo_trx_no;
|
trx_id_t undo_trx_no;
|
||||||
const bool noredo = trx_sys_is_noredo_rseg_slot(
|
|
||||||
rseg->id);
|
|
||||||
|
|
||||||
mtr_start(&mtr);
|
mtr_start(&mtr);
|
||||||
if (noredo) {
|
ut_ad(rseg->is_persistent());
|
||||||
mtr.set_log_mode(MTR_LOG_NO_REDO);
|
|
||||||
}
|
|
||||||
mutex_enter(&(rseg->mutex));
|
mutex_enter(&(rseg->mutex));
|
||||||
|
|
||||||
rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr);
|
rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr);
|
||||||
@@ -509,7 +494,7 @@ loop:
|
|||||||
|
|
||||||
/* calls the trx_purge_remove_log_hdr()
|
/* calls the trx_purge_remove_log_hdr()
|
||||||
inside trx_purge_free_segment(). */
|
inside trx_purge_free_segment(). */
|
||||||
trx_purge_free_segment(rseg, hdr_addr, noredo);
|
trx_purge_free_segment(rseg, hdr_addr);
|
||||||
} else {
|
} else {
|
||||||
/* Remove the log hdr from the rseg history. */
|
/* Remove the log hdr from the rseg history. */
|
||||||
trx_purge_remove_log_hdr(rseg_hdr, log_hdr, &mtr);
|
trx_purge_remove_log_hdr(rseg_hdr, log_hdr, &mtr);
|
||||||
@@ -519,9 +504,6 @@ loop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
mtr_start(&mtr);
|
mtr_start(&mtr);
|
||||||
if (noredo) {
|
|
||||||
mtr.set_log_mode(MTR_LOG_NO_REDO);
|
|
||||||
}
|
|
||||||
mutex_enter(&(rseg->mutex));
|
mutex_enter(&(rseg->mutex));
|
||||||
|
|
||||||
rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr);
|
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
|
/* Step-2: Validation/Qualification checks
|
||||||
a. At-least 2 UNDO tablespaces so even if one UNDO tablespace
|
a. At-least 2 UNDO tablespaces so even if one UNDO tablespace
|
||||||
is being truncated server can continue to operate.
|
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. */
|
b. At-least 1 UNDO tablespace size > threshold. */
|
||||||
if (srv_undo_tablespaces_active < 2
|
if (srv_undo_tablespaces_active < 2 || srv_undo_logs < 3) {
|
||||||
|| (srv_undo_logs < (1 + srv_tmp_undo_logs + 2))) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -846,11 +827,9 @@ trx_purge_mark_undo_for_truncate(
|
|||||||
/* Step-3: Iterate over all the rsegs of selected UNDO tablespace
|
/* Step-3: Iterate over all the rsegs of selected UNDO tablespace
|
||||||
and mark them temporarily unavailable for allocation.*/
|
and mark them temporarily unavailable for allocation.*/
|
||||||
for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) {
|
for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) {
|
||||||
trx_rseg_t* rseg = trx_sys->rseg_array[i];
|
if (trx_rseg_t* rseg = trx_sys->rseg_array[i]) {
|
||||||
|
ut_ad(rseg->is_persistent());
|
||||||
if (rseg != NULL && !trx_sys_is_noredo_rseg_slot(rseg->id)) {
|
if (rseg->space == undo_trunc->get_marked_space_id()) {
|
||||||
if (rseg->space
|
|
||||||
== undo_trunc->get_marked_space_id()) {
|
|
||||||
|
|
||||||
/* Once set this rseg will not be allocated
|
/* Once set this rseg will not be allocated
|
||||||
to new booting transaction but we will wait
|
to new booting transaction but we will wait
|
||||||
|
@@ -1893,13 +1893,7 @@ trx_undo_report_row_operation(
|
|||||||
if (is_temp) {
|
if (is_temp) {
|
||||||
mtr.set_log_mode(MTR_LOG_NO_REDO);
|
mtr.set_log_mode(MTR_LOG_NO_REDO);
|
||||||
|
|
||||||
rseg = trx->rsegs.m_noredo.rseg;
|
rseg = trx->get_temp_rseg();
|
||||||
|
|
||||||
if (!rseg) {
|
|
||||||
trx_assign_rseg(trx);
|
|
||||||
rseg = trx->rsegs.m_noredo.rseg;
|
|
||||||
}
|
|
||||||
|
|
||||||
pundo = &trx->rsegs.m_noredo.undo;
|
pundo = &trx->rsegs.m_noredo.undo;
|
||||||
} else {
|
} else {
|
||||||
ut_ad(!trx->read_only);
|
ut_ad(!trx->read_only);
|
||||||
@@ -2057,16 +2051,16 @@ err_exit:
|
|||||||
|
|
||||||
/*============== BUILDING PREVIOUS VERSION OF A RECORD ===============*/
|
/*============== BUILDING PREVIOUS VERSION OF A RECORD ===============*/
|
||||||
|
|
||||||
/******************************************************************//**
|
/** Copy an undo record to heap.
|
||||||
Copies an undo record to heap. This function can be called if we know that
|
@param[in] roll_ptr roll pointer to a record that exists
|
||||||
the undo log record exists.
|
@param[in] is_temp whether this is a temporary table
|
||||||
@return own: copy of the record */
|
@param[in,out] heap memory heap where copied */
|
||||||
static
|
static
|
||||||
trx_undo_rec_t*
|
trx_undo_rec_t*
|
||||||
trx_undo_get_undo_rec_low(
|
trx_undo_get_undo_rec_low(
|
||||||
/*======================*/
|
roll_ptr_t roll_ptr,
|
||||||
roll_ptr_t roll_ptr, /*!< in: roll pointer to record */
|
bool is_temp,
|
||||||
mem_heap_t* heap) /*!< in: memory heap where copied */
|
mem_heap_t* heap)
|
||||||
{
|
{
|
||||||
trx_undo_rec_t* undo_rec;
|
trx_undo_rec_t* undo_rec;
|
||||||
ulint rseg_id;
|
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,
|
trx_undo_decode_roll_ptr(roll_ptr, &is_insert, &rseg_id, &page_no,
|
||||||
&offset);
|
&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);
|
mtr_start(&mtr);
|
||||||
|
|
||||||
@@ -2093,13 +2090,13 @@ trx_undo_get_undo_rec_low(
|
|||||||
return(undo_rec);
|
return(undo_rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************//**
|
/** Copy an undo record to heap.
|
||||||
Copies an undo record to heap.
|
|
||||||
@param[in] roll_ptr roll pointer to record
|
@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
|
@param[in] trx_id id of the trx that generated
|
||||||
the roll pointer: it points to an
|
the roll pointer: it points to an
|
||||||
undo log of this transaction
|
undo log of this transaction
|
||||||
@param[in] heap memory heap where copied
|
|
||||||
@param[in] name table name
|
@param[in] name table name
|
||||||
@param[out] undo_rec own: copy of the record
|
@param[out] undo_rec own: copy of the record
|
||||||
@retval true if the undo log has been
|
@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))
|
static MY_ATTRIBUTE((warn_unused_result))
|
||||||
bool
|
bool
|
||||||
trx_undo_get_undo_rec(
|
trx_undo_get_undo_rec(
|
||||||
/*==================*/
|
|
||||||
roll_ptr_t roll_ptr,
|
roll_ptr_t roll_ptr,
|
||||||
trx_id_t trx_id,
|
bool is_temp,
|
||||||
mem_heap_t* heap,
|
mem_heap_t* heap,
|
||||||
|
trx_id_t trx_id,
|
||||||
const table_name_t& name,
|
const table_name_t& name,
|
||||||
trx_undo_rec_t** undo_rec)
|
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);
|
missing_history = purge_sys->view.changes_visible(trx_id, name);
|
||||||
if (!missing_history) {
|
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);
|
rw_lock_s_unlock(&purge_sys->latch);
|
||||||
@@ -2203,13 +2200,17 @@ trx_undo_prev_version_build(
|
|||||||
return(true);
|
return(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool is_temp = dict_table_is_temporary(index->table);
|
||||||
rec_trx_id = row_get_rec_trx_id(rec, index, offsets);
|
rec_trx_id = row_get_rec_trx_id(rec, index, offsets);
|
||||||
|
|
||||||
if (trx_undo_get_undo_rec(
|
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) {
|
if (v_status & TRX_UNDO_PREV_IN_PURGE) {
|
||||||
/* We are fetching the record being purged */
|
/* 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 {
|
} else {
|
||||||
/* The undo record may already have been purged,
|
/* The undo record may already have been purged,
|
||||||
during purge or semi-consistent read. */
|
during purge or semi-consistent read. */
|
||||||
|
@@ -90,12 +90,7 @@ trx_rseg_header_create(
|
|||||||
trx_rsegf_set_nth_undo(rsegf, i, FIL_NULL, mtr);
|
trx_rsegf_set_nth_undo(rsegf, i, FIL_NULL, mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!trx_sys_is_noredo_rseg_slot(rseg_slot_no)) {
|
if (space != SRV_TMP_SPACE_ID) {
|
||||||
/* 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. */
|
|
||||||
|
|
||||||
/* Add the rollback segment info to the free slot in
|
/* Add the rollback segment info to the free slot in
|
||||||
the trx system header */
|
the trx system header */
|
||||||
|
|
||||||
@@ -152,51 +147,48 @@ trx_rseg_mem_free(trx_rseg_t* rseg)
|
|||||||
ut_free(rseg);
|
ut_free(rseg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Creates and initializes a rollback segment object.
|
/** Create 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.
|
|
||||||
@param[in] id rollback segment id
|
@param[in] id rollback segment id
|
||||||
@param[in] space space where the segment is placed
|
@param[in] space space where the segment is placed
|
||||||
@param[in] page_no page number of the segment header
|
@param[in] page_no page number of the segment header */
|
||||||
@param[in,out] mtr mini-transaction */
|
|
||||||
static
|
static
|
||||||
void
|
trx_rseg_t*
|
||||||
trx_rseg_mem_create(
|
trx_rseg_mem_create(ulint id, ulint space, ulint page_no)
|
||||||
ulint id,
|
|
||||||
ulint space,
|
|
||||||
ulint page_no,
|
|
||||||
mtr_t* mtr)
|
|
||||||
{
|
{
|
||||||
ulint len;
|
trx_rseg_t* rseg = static_cast<trx_rseg_t*>(
|
||||||
trx_rseg_t* rseg;
|
ut_zalloc_nokey(sizeof *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)));
|
|
||||||
|
|
||||||
rseg->id = id;
|
rseg->id = id;
|
||||||
rseg->space = space;
|
rseg->space = space;
|
||||||
rseg->page_no = page_no;
|
rseg->page_no = page_no;
|
||||||
rseg->trx_ref_count = 0;
|
rseg->last_page_no = FIL_NULL;
|
||||||
rseg->skip_allocation = false;
|
|
||||||
|
|
||||||
if (fsp_is_system_temporary(space)) {
|
mutex_create(rseg->is_persistent()
|
||||||
mutex_create(LATCH_ID_NOREDO_RSEG, &rseg->mutex);
|
? LATCH_ID_REDO_RSEG : LATCH_ID_NOREDO_RSEG,
|
||||||
} else {
|
&rseg->mutex);
|
||||||
mutex_create(LATCH_ID_REDO_RSEG, &rseg->mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
UT_LIST_INIT(rseg->update_undo_list, &trx_undo_t::undo_list);
|
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->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_list, &trx_undo_t::undo_list);
|
||||||
UT_LIST_INIT(rseg->insert_undo_cached, &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->max_size = mtr_read_ulint(
|
||||||
rseg_header + TRX_RSEG_MAX_SIZE, MLOG_4BYTES, mtr);
|
rseg_header + TRX_RSEG_MAX_SIZE, MLOG_4BYTES, mtr);
|
||||||
@@ -240,8 +232,6 @@ trx_rseg_mem_create(
|
|||||||
|
|
||||||
purge_sys->purge_queue.push(elem);
|
purge_sys->purge_queue.push(elem);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
rseg->last_page_no = FIL_NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,54 +242,45 @@ trx_rseg_array_init()
|
|||||||
mtr_t mtr;
|
mtr_t mtr;
|
||||||
|
|
||||||
for (ulint i = 0; i < TRX_SYS_N_RSEGS; i++) {
|
for (ulint i = 0; i < TRX_SYS_N_RSEGS; i++) {
|
||||||
ut_ad(!trx_rseg_get_on_id(i));
|
|
||||||
mtr.start();
|
mtr.start();
|
||||||
trx_sysf_t* sys_header = trx_sysf_get(&mtr);
|
trx_sysf_t* sys_header = trx_sysf_get(&mtr);
|
||||||
ulint page_no = trx_sysf_rseg_get_page_no(
|
ulint page_no = trx_sysf_rseg_get_page_no(
|
||||||
sys_header, i, &mtr);
|
sys_header, i, &mtr);
|
||||||
|
|
||||||
if (page_no != FIL_NULL) {
|
if (page_no != FIL_NULL) {
|
||||||
trx_rseg_mem_create(
|
trx_rseg_t* rseg = trx_rseg_mem_create(
|
||||||
i,
|
i,
|
||||||
trx_sysf_rseg_get_space(sys_header, i, &mtr),
|
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();
|
mtr.commit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/** Create a persistent rollback segment.
|
||||||
Creates a rollback segment.
|
@param[in] space_id system or undo tablespace id */
|
||||||
@return pointer to new rollback segment if create successful */
|
|
||||||
trx_rseg_t*
|
trx_rseg_t*
|
||||||
trx_rseg_create(
|
trx_rseg_create(ulint space_id)
|
||||||
/*============*/
|
|
||||||
ulint space_id, /*!< in: id of UNDO tablespace */
|
|
||||||
ulint nth_free_slot) /*!< in: allocate nth free slot.
|
|
||||||
0 means next free slots. */
|
|
||||||
{
|
{
|
||||||
mtr_t mtr;
|
trx_rseg_t* rseg = NULL;
|
||||||
|
mtr_t mtr;
|
||||||
|
|
||||||
mtr.start();
|
mtr.start();
|
||||||
|
|
||||||
/* To obey the latching order, acquire the file space
|
/* To obey the latching order, acquire the file space
|
||||||
x-latch before the trx_sys->mutex. */
|
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) {
|
ulint slot_no = trx_sysf_rseg_find_free(&mtr);
|
||||||
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 page_no = slot_no == ULINT_UNDEFINED
|
ulint page_no = slot_no == ULINT_UNDEFINED
|
||||||
? FIL_NULL
|
? FIL_NULL
|
||||||
: trx_rseg_header_create(space_id, ULINT_MAX, slot_no, &mtr);
|
: 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(
|
ulint id = trx_sysf_rseg_get_space(
|
||||||
sys_header, slot_no, &mtr);
|
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();
|
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 */
|
#endif /* WITH_WSREP */
|
||||||
|
|
||||||
/****************************************************************//**
|
/** @return an unallocated rollback segment slot in the TRX_SYS header
|
||||||
Looks for a free slot for a rollback segment in the trx system file copy.
|
@retval ULINT_UNDEFINED if not found */
|
||||||
@return slot index or ULINT_UNDEFINED if not found */
|
|
||||||
ulint
|
ulint
|
||||||
trx_sysf_rseg_find_free(
|
trx_sysf_rseg_find_free(mtr_t* mtr)
|
||||||
/*====================*/
|
|
||||||
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. */
|
|
||||||
{
|
{
|
||||||
ulint i;
|
trx_sysf_t* sys_header = trx_sysf_get(mtr);
|
||||||
trx_sysf_t* sys_header;
|
|
||||||
|
|
||||||
sys_header = trx_sysf_get(mtr);
|
for (ulint i = 0; i < TRX_SYS_N_RSEGS; i++) {
|
||||||
|
if (trx_sysf_rseg_get_page_no(sys_header, i, mtr)
|
||||||
ulint found_free_slots = 0;
|
== FIL_NULL) {
|
||||||
for (i = 0; i < TRX_SYS_N_RSEGS; i++) {
|
return(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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return(ULINT_UNDEFINED);
|
return(ULINT_UNDEFINED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************//**
|
/** Count the number of initialized persistent rollback segment slots. */
|
||||||
Looks for used slots for redo rollback segment.
|
|
||||||
@return number of used slots */
|
|
||||||
static
|
static
|
||||||
ulint
|
void
|
||||||
trx_sysf_used_slots_for_redo_rseg(
|
trx_sysf_get_n_rseg_slots()
|
||||||
/*==============================*/
|
|
||||||
mtr_t* mtr) /*!< in: mtr */
|
|
||||||
{
|
{
|
||||||
trx_sysf_t* sys_header;
|
mtr_t mtr;
|
||||||
ulint n_used = 0;
|
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++) {
|
for (ulint i = 0; i < TRX_SYS_N_RSEGS; i++) {
|
||||||
|
srv_available_undo_logs
|
||||||
if (trx_sys_is_noredo_rseg_slot(i)) {
|
+= trx_sysf_rseg_get_page_no(sys_header, i, &mtr)
|
||||||
continue;
|
!= FIL_NULL;
|
||||||
}
|
|
||||||
|
|
||||||
ulint page_no;
|
|
||||||
|
|
||||||
page_no = trx_sysf_rseg_get_page_no(sys_header, i, mtr);
|
|
||||||
|
|
||||||
if (page_no != FIL_NULL) {
|
|
||||||
++n_used;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return(n_used);
|
mtr.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************//**
|
/*****************************************************************//**
|
||||||
@@ -532,7 +497,7 @@ trx_sysf_create(
|
|||||||
+ page - sys_header, mtr);
|
+ page - sys_header, mtr);
|
||||||
|
|
||||||
/* Create the first rollback segment in the SYSTEM tablespace */
|
/* 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,
|
page_no = trx_rseg_header_create(TRX_SYS_SPACE,
|
||||||
ULINT_MAX, slot_no, mtr);
|
ULINT_MAX, slot_no, mtr);
|
||||||
|
|
||||||
@@ -904,118 +869,69 @@ trx_sys_file_format_close(void)
|
|||||||
mutex_free(&file_format_max.mutex);
|
mutex_free(&file_format_max.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/** Create the rollback segments.
|
||||||
Creates non-redo rollback segments.
|
@return whether the creation succeeded */
|
||||||
@return number of non-redo rollback segments created. */
|
bool
|
||||||
static
|
trx_sys_create_rsegs()
|
||||||
ulint
|
|
||||||
trx_sys_create_noredo_rsegs(
|
|
||||||
/*========================*/
|
|
||||||
ulint n_nonredo_rseg) /*!< number of non-redo rollback segment
|
|
||||||
to create. */
|
|
||||||
{
|
{
|
||||||
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.
|
srv_undo_logs determines how many of the
|
||||||
non-redo rollback segments don't perform redo logging and so
|
srv_available_undo_logs rollback segments may be used for
|
||||||
are used for undo logging of objects/table that don't need to be
|
logging new transactions. */
|
||||||
recover on crash.
|
ut_ad(srv_undo_tablespaces < TRX_SYS_N_RSEGS);
|
||||||
(Non-Redo rollback segments are created on every server startup).
|
ut_ad(srv_undo_logs <= TRX_SYS_N_RSEGS);
|
||||||
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);
|
|
||||||
|
|
||||||
if (srv_read_only_mode) {
|
if (srv_read_only_mode) {
|
||||||
return(ULINT_UNDEFINED);
|
srv_undo_logs = srv_available_undo_logs = ULONG_UNDEFINED;
|
||||||
|
return(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create non-redo rollback segments. */
|
/* Create temporary rollback segments. */
|
||||||
n_noredo_created = trx_sys_create_noredo_rsegs(n_tmp_rsegs);
|
trx_temp_rseg_create();
|
||||||
|
|
||||||
/* This is executed in single-threaded mode therefore it is not
|
/* This is executed in single-threaded mode therefore it is not
|
||||||
necessary to use the same mtr in trx_rseg_create(). n_used cannot
|
necessary to use the same mtr in trx_rseg_create(). n_used cannot
|
||||||
change while the function is executing. */
|
change while the function is executing. */
|
||||||
mtr_start(&mtr);
|
trx_sysf_get_n_rseg_slots();
|
||||||
n_used = trx_sysf_used_slots_for_redo_rseg(&mtr) + n_noredo_created;
|
|
||||||
mtr_commit(&mtr);
|
|
||||||
|
|
||||||
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
|
/* The first persistent rollback segment is always initialized
|
||||||
system tablespace. */
|
in the system tablespace. */
|
||||||
ulint n_redo_active;
|
ut_a(srv_available_undo_logs > 0);
|
||||||
if (n_rsegs <= n_tmp_rsegs) {
|
|
||||||
n_redo_active = 1;
|
if (srv_force_recovery) {
|
||||||
} else if (n_rsegs > n_used) {
|
/* Do not create additional rollback segments if
|
||||||
n_redo_active = n_used - n_tmp_rsegs;
|
innodb_force_recovery has been set. */
|
||||||
|
if (srv_undo_logs > srv_available_undo_logs) {
|
||||||
|
srv_undo_logs = srv_available_undo_logs;
|
||||||
|
}
|
||||||
} else {
|
} 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
|
if (!trx_rseg_create(space)) {
|
||||||
has been set and the database was not shutdown cleanly. */
|
ib::error() << "Unable to allocate the"
|
||||||
if (!srv_force_recovery && !recv_needed_recovery && n_used < n_rsegs) {
|
" requested innodb_undo_logs";
|
||||||
ulint i;
|
return(false);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ib::info() << n_used - srv_tmp_undo_logs
|
ut_ad(srv_undo_logs <= srv_available_undo_logs);
|
||||||
<< " redo rollback segment(s) found. "
|
|
||||||
<< n_redo_active
|
|
||||||
<< " redo rollback segment(s) are active.";
|
|
||||||
|
|
||||||
ib::info() << n_noredo_created << " non-redo rollback segment(s) are"
|
ib::info() << srv_undo_logs << " out of " << srv_available_undo_logs
|
||||||
" active.";
|
<< " rollback segments are active.";
|
||||||
|
|
||||||
return(n_used);
|
return(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
@@ -1027,9 +943,7 @@ trx_sys_close(void)
|
|||||||
ut_ad(trx_sys != NULL);
|
ut_ad(trx_sys != NULL);
|
||||||
ut_ad(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS);
|
ut_ad(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS);
|
||||||
|
|
||||||
ulint size = trx_sys->mvcc->size();
|
if (ulint size = trx_sys->mvcc->size()) {
|
||||||
|
|
||||||
if (size > 0) {
|
|
||||||
ib::error() << "All read views were not closed before"
|
ib::error() << "All read views were not closed before"
|
||||||
" shutdown: " << size << " read views open";
|
" shutdown: " << size << " read views open";
|
||||||
}
|
}
|
||||||
@@ -1060,6 +974,10 @@ trx_sys_close(void)
|
|||||||
if (trx_rseg_t* rseg = trx_sys->rseg_array[i]) {
|
if (trx_rseg_t* rseg = trx_sys->rseg_array[i]) {
|
||||||
trx_rseg_mem_free(rseg);
|
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);
|
UT_DELETE(trx_sys->mvcc);
|
||||||
|
@@ -1090,43 +1090,34 @@ trx_lists_init_at_db_start()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************//**
|
/** Assign a persistent rollback segment in a round-robin fashion,
|
||||||
Get next redo rollback segment. (Segment are assigned in round-robin fashion).
|
evenly distributed between 0 and innodb_undo_logs-1
|
||||||
@return assigned rollback segment instance */
|
@return persistent rollback segment
|
||||||
|
@retval NULL if innodb_read_only */
|
||||||
static
|
static
|
||||||
trx_rseg_t*
|
trx_rseg_t*
|
||||||
get_next_redo_rseg(
|
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_t* rseg;
|
if (srv_read_only_mode) {
|
||||||
static ulint redo_rseg_slot = 0;
|
ut_ad(srv_undo_logs == ULONG_UNDEFINED);
|
||||||
ulint slot = 0;
|
return(NULL);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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
|
#ifdef UNIV_DEBUG
|
||||||
ulint start_scan_slot = slot;
|
ulint start_scan_slot = slot;
|
||||||
bool look_for_rollover = false;
|
bool look_for_rollover = false;
|
||||||
@@ -1134,8 +1125,7 @@ get_next_redo_rseg(
|
|||||||
|
|
||||||
bool allocated = false;
|
bool allocated = false;
|
||||||
|
|
||||||
while (!allocated) {
|
do {
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
rseg = trx_sys->rseg_array[slot];
|
rseg = trx_sys->rseg_array[slot];
|
||||||
|
|
||||||
@@ -1148,37 +1138,31 @@ get_next_redo_rseg(
|
|||||||
look_for_rollover = true;
|
look_for_rollover = true;
|
||||||
#endif /* UNIV_DEBUG */
|
#endif /* UNIV_DEBUG */
|
||||||
|
|
||||||
slot = (slot + 1) % max_undo_logs;
|
slot = (slot + 1) % srv_undo_logs;
|
||||||
|
|
||||||
/* Skip slots allocated for noredo rsegs */
|
|
||||||
while (trx_sys_is_noredo_rseg_slot(slot)) {
|
|
||||||
slot = (slot + 1) % max_undo_logs;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rseg == NULL) {
|
if (rseg == NULL) {
|
||||||
continue;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1191,129 +1175,43 @@ get_next_redo_rseg(
|
|||||||
allocated = true;
|
allocated = true;
|
||||||
}
|
}
|
||||||
mutex_exit(&rseg->mutex);
|
mutex_exit(&rseg->mutex);
|
||||||
}
|
} while (!allocated);
|
||||||
|
|
||||||
ut_ad(rseg->trx_ref_count > 0);
|
ut_ad(rseg->trx_ref_count > 0);
|
||||||
ut_ad(!trx_sys_is_noredo_rseg_slot(rseg->id));
|
ut_ad(rseg->is_persistent());
|
||||||
return(rseg);
|
return(rseg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************//**
|
/** Assign a rollback segment for modifying temporary tables.
|
||||||
Get next noredo rollback segment.
|
@return the assigned rollback segment */
|
||||||
@return assigned rollback segment instance */
|
|
||||||
static
|
|
||||||
trx_rseg_t*
|
trx_rseg_t*
|
||||||
get_next_noredo_rseg(
|
trx_t::assign_temp_rseg()
|
||||||
/*=================*/
|
|
||||||
ulong max_undo_logs) /*!< in: maximum number of UNDO logs to use */
|
|
||||||
{
|
{
|
||||||
trx_rseg_t* rseg;
|
ut_ad(!rsegs.m_noredo.rseg);
|
||||||
static ulint noredo_rseg_slot = 1;
|
ut_ad(!trx_is_autocommit_non_locking(this));
|
||||||
ulint slot = 0;
|
compile_time_assert(ut_is_2pow(TRX_SYS_N_RSEGS));
|
||||||
|
|
||||||
slot = noredo_rseg_slot++;
|
/* Choose a temporary rollback segment between 0 and 127
|
||||||
slot = slot % max_undo_logs;
|
in a round-robin fashion. Because rseg_slot is not protected by
|
||||||
while (!trx_sys_is_noredo_rseg_slot(slot)) {
|
atomics or any mutex, race conditions are possible, meaning that
|
||||||
slot = (slot + 1) % max_undo_logs;
|
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 (;;) {
|
if (id == 0) {
|
||||||
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) {
|
|
||||||
mutex_enter(&trx_sys->mutex);
|
mutex_enter(&trx_sys->mutex);
|
||||||
|
id = trx_sys_get_new_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));
|
||||||
trx_sys->rw_trx_ids.push_back(trx->id);
|
|
||||||
|
|
||||||
trx_sys->rw_trx_set.insert(TrxTrack(trx->id, trx));
|
|
||||||
|
|
||||||
mutex_exit(&trx_sys->mutex);
|
mutex_exit(&trx_sys->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ut_ad(!rseg->is_persistent());
|
||||||
|
return(rseg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************//**
|
/****************************************************************//**
|
||||||
@@ -1388,9 +1286,7 @@ trx_start_low(
|
|||||||
if (!trx->read_only
|
if (!trx->read_only
|
||||||
&& (trx->mysql_thd == 0 || read_write || trx->ddl)) {
|
&& (trx->mysql_thd == 0 || read_write || trx->ddl)) {
|
||||||
|
|
||||||
trx->rsegs.m_redo.rseg = trx_assign_rseg_low(
|
trx->rsegs.m_redo.rseg = trx_assign_rseg_low();
|
||||||
srv_undo_logs, srv_undo_tablespaces,
|
|
||||||
TRX_RSEG_TYPE_REDO);
|
|
||||||
|
|
||||||
/* Temporary rseg is assigned only if the transaction
|
/* Temporary rseg is assigned only if the transaction
|
||||||
updates a temporary table */
|
updates a temporary table */
|
||||||
@@ -2969,8 +2865,6 @@ trx_start_if_not_started_xa_low(
|
|||||||
trx_sys_t::rw_trx_list. */
|
trx_sys_t::rw_trx_list. */
|
||||||
if (!trx->read_only) {
|
if (!trx->read_only) {
|
||||||
trx_set_rw_mode(trx);
|
trx_set_rw_mode(trx);
|
||||||
} else if (!srv_read_only_mode) {
|
|
||||||
trx_assign_rseg(trx);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -3116,8 +3010,7 @@ trx_set_rw_mode(
|
|||||||
that both threads are synced by acquring trx->mutex to avoid decision
|
that both threads are synced by acquring trx->mutex to avoid decision
|
||||||
based on in-consistent view formed during promotion. */
|
based on in-consistent view formed during promotion. */
|
||||||
|
|
||||||
trx->rsegs.m_redo.rseg = trx_assign_rseg_low(
|
trx->rsegs.m_redo.rseg = trx_assign_rseg_low();
|
||||||
srv_undo_logs, srv_undo_tablespaces, TRX_RSEG_TYPE_REDO);
|
|
||||||
|
|
||||||
ut_ad(trx->rsegs.m_redo.rseg != 0);
|
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)
|
trx_undo_truncate_end(trx_undo_t* undo, undo_no_t limit, bool is_temp)
|
||||||
{
|
{
|
||||||
ut_ad(mutex_own(&undo->rseg->mutex));
|
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 (;;) {
|
for (;;) {
|
||||||
mtr_t mtr;
|
mtr_t mtr;
|
||||||
@@ -1102,7 +1102,7 @@ trx_undo_truncate_start(
|
|||||||
loop:
|
loop:
|
||||||
mtr_start(&mtr);
|
mtr_start(&mtr);
|
||||||
|
|
||||||
if (trx_sys_is_noredo_rseg_slot(rseg->id)) {
|
if (!rseg->is_persistent()) {
|
||||||
mtr.set_log_mode(MTR_LOG_NO_REDO);
|
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_undo_commit_cleanup(trx_undo_t* undo, bool is_temp)
|
||||||
{
|
{
|
||||||
trx_rseg_t* rseg = undo->rseg;
|
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);
|
mutex_enter(&rseg->mutex);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user