From dfdfeecb03edaf5660f5e15337381dda6f83102c Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Tue, 14 Jul 2020 12:09:10 +0530 Subject: MDEV-22851: Engine independent index statistics are incorrect for large tables on Windows An oveflow was happening on windows because on Windows sizeof(ulong) is 4 bytes while it is 8 bytes on Linux. Switched avg_frequency and avg length for column statistics to ulonglong. Switched avg_frequency for index statistics to ulonglong. --- mysql-test/r/stat_tables_innodb.result | 29 +++++++++++++++++++++++++++++ mysql-test/t/stat_tables_innodb.test | 21 +++++++++++++++++++++ sql/sql_statistics.cc | 14 +++++++------- sql/sql_statistics.h | 18 ++++++++++-------- 4 files changed, 67 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/stat_tables_innodb.result b/mysql-test/r/stat_tables_innodb.result index b8bed681465..5f393dde05e 100644 --- a/mysql-test/r/stat_tables_innodb.result +++ b/mysql-test/r/stat_tables_innodb.result @@ -770,4 +770,33 @@ set @@optimizer_use_condition_selectivity= @save_optimizer_use_condition_selecti set @save_optimizer_switch=@@optimizer_switch; set use_stat_tables=@save_use_stat_tables; set optimizer_switch=@save_optimizer_switch_for_stat_tables_test; +# +# MDEV-22851: Engine independent index statistics are incorrect for large tables on Windows. +# +CREATE TABLE t1 AS SELECT TABLE_CATALOG FROM INFORMATION_SCHEMA.COLUMNS; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +SET @save_use_stat_tables= @@use_stat_tables; +SET use_stat_tables= preferably; +SELECT count(*) FROM t1; +count(*) +54336 +CREATE INDEX idx ON t1(TABLE_CATALOG); +Warnings: +Warning 1071 Specified key was too long; max key length is 767 bytes +ANALYZE TABLE t1 PERSISTENT FOR COLUMNS (TABLE_CATALOG) INDEXES (idx); +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +SELECT * FROM mysql.index_stats where table_name='t1'; +db_name table_name index_name prefix_arity avg_frequency +test t1 idx 1 NULL +SELECT * FROM mysql.column_stats where table_name='t1'; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 TABLE_CATALOG def def 0.0000 3.0000 54336.0000 0 NULL NULL +SET use_stat_tables= @save_use_stat_tables; +DROP TABLE t1; SET SESSION STORAGE_ENGINE=DEFAULT; diff --git a/mysql-test/t/stat_tables_innodb.test b/mysql-test/t/stat_tables_innodb.test index 04e81de8f9d..e4a11955aba 100644 --- a/mysql-test/t/stat_tables_innodb.test +++ b/mysql-test/t/stat_tables_innodb.test @@ -9,4 +9,25 @@ set optimizer_switch='extended_keys=on'; set optimizer_switch=@save_optimizer_switch_for_stat_tables_test; +--echo # +--echo # MDEV-22851: Engine independent index statistics are incorrect for large tables on Windows. +--echo # + +CREATE TABLE t1 AS SELECT TABLE_CATALOG FROM INFORMATION_SCHEMA.COLUMNS; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; + +SET @save_use_stat_tables= @@use_stat_tables; +SET use_stat_tables= preferably; +SELECT count(*) FROM t1; +CREATE INDEX idx ON t1(TABLE_CATALOG); +ANALYZE TABLE t1 PERSISTENT FOR COLUMNS (TABLE_CATALOG) INDEXES (idx); +SELECT * FROM mysql.index_stats where table_name='t1'; +SELECT * FROM mysql.column_stats where table_name='t1'; +SET use_stat_tables= @save_use_stat_tables; +DROP TABLE t1; + SET SESSION STORAGE_ENGINE=DEFAULT; diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index ae02254c745..c2581fd6105 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -2096,8 +2096,8 @@ int alloc_statistics_for_table(THD* thd, TABLE *table) sizeof(Index_statistics) * keys); uint key_parts= table->s->ext_key_parts; - ulong *idx_avg_frequency= (ulong*) alloc_root(&table->mem_root, - sizeof(ulong) * key_parts); + ulonglong *idx_avg_frequency= (ulonglong*) alloc_root(&table->mem_root, + sizeof(ulonglong) * key_parts); uint columns= 0; for (field_ptr= table->field; *field_ptr; field_ptr++) @@ -2142,7 +2142,7 @@ int alloc_statistics_for_table(THD* thd, TABLE *table) } } - memset(idx_avg_frequency, 0, sizeof(ulong) * key_parts); + memset(idx_avg_frequency, 0, sizeof(ulonglong) * key_parts); KEY *key_info, *end; for (key_info= table->key_info, end= key_info + table->s->keys; @@ -2258,14 +2258,14 @@ static int alloc_statistics_for_table_share(THD* thd, TABLE_SHARE *table_share) } uint key_parts= table_share->ext_key_parts; - ulong *idx_avg_frequency= table_stats->idx_avg_frequency; + ulonglong *idx_avg_frequency= table_stats->idx_avg_frequency; if (!idx_avg_frequency) { - idx_avg_frequency= (ulong*) alloc_root(&stats_cb->mem_root, - sizeof(ulong) * key_parts); + idx_avg_frequency= (ulonglong*) alloc_root(&stats_cb->mem_root, + sizeof(ulonglong) * key_parts); if (idx_avg_frequency) { - memset(idx_avg_frequency, 0, sizeof(ulong) * key_parts); + memset(idx_avg_frequency, 0, sizeof(ulonglong) * key_parts); table_stats->idx_avg_frequency= idx_avg_frequency; for (key_info= table_share->key_info, end= key_info + keys; key_info < end; diff --git a/sql/sql_statistics.h b/sql/sql_statistics.h index 151618ca365..903d164ca99 100644 --- a/sql/sql_statistics.h +++ b/sql/sql_statistics.h @@ -279,7 +279,9 @@ public: uchar *min_max_record_buffers; /* Record buffers for min/max values */ Column_statistics *column_stats; /* Array of statistical data for columns */ Index_statistics *index_stats; /* Array of statistical data for indexes */ - ulong *idx_avg_frequency; /* Array of records per key for index prefixes */ + + /* Array of records per key for index prefixes */ + ulonglong *idx_avg_frequency; uchar *histograms; /* Sequence of histograms */ }; @@ -331,7 +333,7 @@ private: CHAR values are stripped of trailing spaces. Flexible values are stripped of their length prefixes. */ - ulong avg_length; + ulonglong avg_length; /* The ratio N/D multiplied by the scale factor Scale_factor_avg_frequency, @@ -339,7 +341,7 @@ private: N is the number of rows with not null value in the column, D the number of distinct values among them */ - ulong avg_frequency; + ulonglong avg_frequency; public: @@ -389,12 +391,12 @@ public: void set_avg_length (double val) { - avg_length= (ulong) (val * Scale_factor_avg_length); + avg_length= (ulonglong) (val * Scale_factor_avg_length); } void set_avg_frequency (double val) { - avg_frequency= (ulong) (val * Scale_factor_avg_frequency); + avg_frequency= (ulonglong) (val * Scale_factor_avg_frequency); } bool min_max_values_are_provided() @@ -433,11 +435,11 @@ private: in the first k components, and D is the number of distinct k-component prefixes among them */ - ulong *avg_frequency; + ulonglong *avg_frequency; public: - void init_avg_frequency(ulong *ptr) { avg_frequency= ptr; } + void init_avg_frequency(ulonglong *ptr) { avg_frequency= ptr; } bool avg_frequency_is_inited() { return avg_frequency != NULL; } @@ -448,7 +450,7 @@ public: void set_avg_frequency(uint i, double val) { - avg_frequency[i]= (ulong) (val * Scale_factor_avg_frequency); + avg_frequency[i]= (ulonglong) (val * Scale_factor_avg_frequency); } }; -- cgit v1.2.1 From 7473e1841c630d86f1873a2a7afacb53955b3f6f Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Tue, 5 May 2020 11:57:20 +1000 Subject: check_linker_flag: use for linker flags -Wl,-z,relro,-z,now are linker flags and should be checked as such. TODO: perform module, exe shared checks separately rather than a pure linker check. --- CMakeLists.txt | 3 ++- cmake/check_linker_flag.cmake | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 cmake/check_linker_flag.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 05e3c52f1e4..660b3ee46bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -186,6 +186,7 @@ ENDIF() OPTION(NOT_FOR_DISTRIBUTION "Allow linking with GPLv2-incompatible system libraries. Only set it you never plan to distribute the resulting binaries" OFF) INCLUDE(check_compiler_flag) +INCLUDE(check_linker_flag) OPTION(WITH_ASAN "Enable address sanitizer" OFF) IF (WITH_ASAN) @@ -234,7 +235,7 @@ IF(SECURITY_HARDENED) ENDIF() # security-enhancing flags MY_CHECK_AND_SET_COMPILER_FLAG("-pie -fPIC") - MY_CHECK_AND_SET_COMPILER_FLAG("-Wl,-z,relro,-z,now") + MY_CHECK_AND_SET_LINKER_FLAG("-Wl,-z,relro,-z,now") MY_CHECK_AND_SET_COMPILER_FLAG("-fstack-protector --param=ssp-buffer-size=4") MY_CHECK_AND_SET_COMPILER_FLAG("-D_FORTIFY_SOURCE=2" RELEASE RELWITHDEBINFO) ENDIF() diff --git a/cmake/check_linker_flag.cmake b/cmake/check_linker_flag.cmake new file mode 100644 index 00000000000..ff4b91e89f6 --- /dev/null +++ b/cmake/check_linker_flag.cmake @@ -0,0 +1,27 @@ +include(CheckCXXSourceCompiles) + +FUNCTION(MY_CHECK_AND_SET_LINKER_FLAG flag_to_set) + # Let's avoid expensive compiler tests on Windows: + IF(WIN32) + RETURN() + ENDIF() + STRING(REGEX REPLACE "[-,= +]" "_" result "HAVE_LINK_FLAG_${flag_to_set}") + SET(SAVE_CMAKE_REQUIRED_LINK_OPTIONS "${CMAKE_REQUIRED_LINK_OPTIONS}") + STRING(REGEX REPLACE "^-Wno-" "-W" flag_to_check ${flag_to_set}) + SET(CMAKE_REQUIRED_LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS} ${flag_to_check}) + CHECK_CXX_SOURCE_COMPILES("int main(void) { return 0; }" ${result}) + SET(CMAKE_REQUIRED_LINK_OPTIONS "${SAVE_CMAKE_REQUIRED_LINK_OPTIONS}") + IF (${result}) + FOREACH(linktype SHARED MODULE EXE) + IF(ARGN) + FOREACH(type ${ARGN}) + SET(CMAKE_${linktype}_LINKER_FLAGS_${type} + "${CMAKE_${linktype}_LINKER_FLAGS_${type}} ${flag_to_set}" PARENT_SCOPE) + ENDFOREACH() + ELSE() + SET(CMAKE_${linktype}_LINKER_FLAGS + "${CMAKE_${linktype}_LINKER_FLAGS} ${flag_to_set}" PARENT_SCOPE) + ENDIF() + ENDFOREACH() + ENDIF() +ENDFUNCTION() -- cgit v1.2.1 From 4412a461a1eb5e061dcbf3bdd935f7eef01bfeb5 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Tue, 12 May 2020 13:29:17 +0200 Subject: MDEV-20401: Server incorrectly auto-sets lower_case_file_system value Server auto-sets lower_case_file_system value based on default datadir's behavior instead of instead of using the directory specified by the user through the configuration file or command line options. This patch fixes this problem. --- sql/mysqld.cc | 8 +++++--- sql/sys_vars.cc | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 594f50b72f2..6a5162e2f03 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4538,8 +4538,10 @@ static int init_common_variables() get corrupted if accesses with names of different case. */ DBUG_PRINT("info", ("lower_case_table_names: %d", lower_case_table_names)); + if(mysql_real_data_home_ptr == NULL || *mysql_real_data_home_ptr == 0) + mysql_real_data_home_ptr= mysql_real_data_home; SYSVAR_AUTOSIZE(lower_case_file_system, - test_if_case_insensitive(mysql_real_data_home)); + test_if_case_insensitive(mysql_real_data_home_ptr)); if (!lower_case_table_names && lower_case_file_system == 1) { if (lower_case_table_names_used) @@ -4556,7 +4558,7 @@ static int init_common_variables() { if (global_system_variables.log_warnings) sql_print_warning("Setting lower_case_table_names=2 because file " - "system for %s is case insensitive", mysql_real_data_home); + "system for %s is case insensitive", mysql_real_data_home_ptr); SYSVAR_AUTOSIZE(lower_case_table_names, 2); } } @@ -4567,7 +4569,7 @@ static int init_common_variables() sql_print_warning("lower_case_table_names was set to 2, even though your " "the file system '%s' is case sensitive. Now setting " "lower_case_table_names to 0 to avoid future problems.", - mysql_real_data_home); + mysql_real_data_home_ptr); SYSVAR_AUTOSIZE(lower_case_table_names, 0); } else diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 7dc1d1ab6e8..52565d696b9 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -818,7 +818,7 @@ static Sys_var_ulong Sys_connect_timeout( static Sys_var_charptr Sys_datadir( "datadir", "Path to the database root directory", - READ_ONLY GLOBAL_VAR(mysql_real_data_home_ptr), + PARSED_EARLY READ_ONLY GLOBAL_VAR(mysql_real_data_home_ptr), CMD_LINE(REQUIRED_ARG, 'h'), IN_FS_CHARSET, DEFAULT(mysql_real_data_home)); #ifndef DBUG_OFF -- cgit v1.2.1 From b3cae9db112d69e8472d4f965805db7c61a6c44c Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Tue, 12 May 2020 13:29:17 +0200 Subject: MDEV-20401: Server incorrectly auto-sets lower_case_file_system value Server auto-sets lower_case_file_system value based on default datadir's behavior instead of instead of using the directory specified by the user through the configuration file or command line options. This patch fixes this problem. --- sql/mysqld.cc | 8 +++++--- sql/sys_vars.cc | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index afe969b6e8d..44f8558e474 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4674,8 +4674,10 @@ static int init_common_variables() get corrupted if accesses with names of different case. */ DBUG_PRINT("info", ("lower_case_table_names: %d", lower_case_table_names)); + if(mysql_real_data_home_ptr == NULL || *mysql_real_data_home_ptr == 0) + mysql_real_data_home_ptr= mysql_real_data_home; SYSVAR_AUTOSIZE(lower_case_file_system, - test_if_case_insensitive(mysql_real_data_home)); + test_if_case_insensitive(mysql_real_data_home_ptr)); if (!lower_case_table_names && lower_case_file_system == 1) { if (lower_case_table_names_used) @@ -4692,7 +4694,7 @@ static int init_common_variables() { if (global_system_variables.log_warnings) sql_print_warning("Setting lower_case_table_names=2 because file " - "system for %s is case insensitive", mysql_real_data_home); + "system for %s is case insensitive", mysql_real_data_home_ptr); SYSVAR_AUTOSIZE(lower_case_table_names, 2); } } @@ -4703,7 +4705,7 @@ static int init_common_variables() sql_print_warning("lower_case_table_names was set to 2, even though your " "the file system '%s' is case sensitive. Now setting " "lower_case_table_names to 0 to avoid future problems.", - mysql_real_data_home); + mysql_real_data_home_ptr); SYSVAR_AUTOSIZE(lower_case_table_names, 0); } else diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index af261299496..fa62667b863 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -839,7 +839,7 @@ static Sys_var_ulong Sys_connect_timeout( static Sys_var_charptr Sys_datadir( "datadir", "Path to the database root directory", - READ_ONLY GLOBAL_VAR(mysql_real_data_home_ptr), + PARSED_EARLY READ_ONLY GLOBAL_VAR(mysql_real_data_home_ptr), CMD_LINE(REQUIRED_ARG, 'h'), IN_FS_CHARSET, DEFAULT(mysql_real_data_home)); #ifndef DBUG_OFF -- cgit v1.2.1 From 1ba8df4c60cd0e149c5a37ef88bee96dfd7cd95d Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Thu, 16 Jul 2020 16:31:27 +0200 Subject: MDEV-20401: revert unnecessary change --- sql/sys_vars.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 52565d696b9..7dc1d1ab6e8 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -818,7 +818,7 @@ static Sys_var_ulong Sys_connect_timeout( static Sys_var_charptr Sys_datadir( "datadir", "Path to the database root directory", - PARSED_EARLY READ_ONLY GLOBAL_VAR(mysql_real_data_home_ptr), + READ_ONLY GLOBAL_VAR(mysql_real_data_home_ptr), CMD_LINE(REQUIRED_ARG, 'h'), IN_FS_CHARSET, DEFAULT(mysql_real_data_home)); #ifndef DBUG_OFF -- cgit v1.2.1 From a1e52e7f32cee7c204078db4c4beb88250d7e1f6 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Thu, 16 Jul 2020 16:40:37 +0200 Subject: MDEV-20401: revert unnecessary change --- sql/sys_vars.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index fa62667b863..af261299496 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -839,7 +839,7 @@ static Sys_var_ulong Sys_connect_timeout( static Sys_var_charptr Sys_datadir( "datadir", "Path to the database root directory", - PARSED_EARLY READ_ONLY GLOBAL_VAR(mysql_real_data_home_ptr), + READ_ONLY GLOBAL_VAR(mysql_real_data_home_ptr), CMD_LINE(REQUIRED_ARG, 'h'), IN_FS_CHARSET, DEFAULT(mysql_real_data_home)); #ifndef DBUG_OFF -- cgit v1.2.1 From 2cae58f8918f64c77227cfa07ab2fd24c3580f81 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Fri, 17 Jul 2020 12:20:23 +0400 Subject: MDEV-18371 Server crashes in ha_innobase::cmp_ref upon UPDATE with PARTITION clause. m_file[0] not always is a good sample. --- mysql-test/main/partition_explicit_prune.result | 18 ++++++++++++++++++ mysql-test/main/partition_explicit_prune.test | 12 ++++++++++++ sql/ha_partition.cc | 7 ++++--- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/mysql-test/main/partition_explicit_prune.result b/mysql-test/main/partition_explicit_prune.result index 951b21db3e1..0c102501a9d 100644 --- a/mysql-test/main/partition_explicit_prune.result +++ b/mysql-test/main/partition_explicit_prune.result @@ -1888,4 +1888,22 @@ ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; SELECT * FROM t1 PARTITION (p0); i UNLOCK TABLES; +DROP TABLE t1; +# +# MDEV-18371 Server crashes in ha_innobase::cmp_ref upon UPDATE with PARTITION clause. +# +CREATE TABLE t1 (a INT, b INT, KEY (a)) ENGINE=InnoDB PARTITION BY KEY(b) PARTITIONS 4; +INSERT INTO t1 VALUES (3,0),(8,2),(7,8),(3,4),(2,4),(0,7),(4,3),(3,6); +FLUSH TABLES; +UPDATE t1 PARTITION (p3,p1) SET a = 2 WHERE a = 3; +SELECT * FROM t1; +a b +2 0 +7 8 +2 4 +2 4 +0 7 +4 3 +8 2 +2 6 DROP TABLE t1, t2; diff --git a/mysql-test/main/partition_explicit_prune.test b/mysql-test/main/partition_explicit_prune.test index b8b6e480ce9..0be21396148 100644 --- a/mysql-test/main/partition_explicit_prune.test +++ b/mysql-test/main/partition_explicit_prune.test @@ -874,6 +874,18 @@ SELECT * FROM t1 PARTITION (p0); ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; SELECT * FROM t1 PARTITION (p0); UNLOCK TABLES; +DROP TABLE t1; + +--echo # +--echo # MDEV-18371 Server crashes in ha_innobase::cmp_ref upon UPDATE with PARTITION clause. +--echo # + +CREATE TABLE t1 (a INT, b INT, KEY (a)) ENGINE=InnoDB PARTITION BY KEY(b) PARTITIONS 4; +INSERT INTO t1 VALUES (3,0),(8,2),(7,8),(3,4),(2,4),(0,7),(4,3),(3,6); +FLUSH TABLES; +UPDATE t1 PARTITION (p3,p1) SET a = 2 WHERE a = 3; +SELECT * FROM t1; + # Cleanup DROP TABLE t1, t2; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index e19f21de006..92f527de3bc 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -5580,8 +5580,9 @@ extern "C" int cmp_key_rowid_part_id(void *ptr, uchar *ref1, uchar *ref2) { return res; } - if ((res= file->m_file[0]->cmp_ref(ref1 + PARTITION_BYTES_IN_POS + file->m_rec_length, - ref2 + PARTITION_BYTES_IN_POS + file->m_rec_length))) + if ((res= file->get_open_file_sample()->cmp_ref(ref1 + + PARTITION_BYTES_IN_POS + file->m_rec_length, + ref2 + PARTITION_BYTES_IN_POS + file->m_rec_length))) { return res; } @@ -9577,7 +9578,7 @@ uint8 ha_partition::table_cache_type() { DBUG_ENTER("ha_partition::table_cache_type"); - DBUG_RETURN(m_file[0]->table_cache_type()); + DBUG_RETURN(get_open_file_sample()->table_cache_type()); } -- cgit v1.2.1 From c400ef2586bd188858ff43f2120fdf17475f2fdb Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Fri, 17 Jul 2020 22:00:36 +0530 Subject: Making the stat_tables_innodb test deterministic --- mysql-test/r/stat_tables_innodb.result | 21 ++++++++------------- mysql-test/t/stat_tables_innodb.test | 15 +++++++-------- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/mysql-test/r/stat_tables_innodb.result b/mysql-test/r/stat_tables_innodb.result index 5f393dde05e..fd9f337c30d 100644 --- a/mysql-test/r/stat_tables_innodb.result +++ b/mysql-test/r/stat_tables_innodb.result @@ -773,30 +773,25 @@ set optimizer_switch=@save_optimizer_switch_for_stat_tables_test; # # MDEV-22851: Engine independent index statistics are incorrect for large tables on Windows. # -CREATE TABLE t1 AS SELECT TABLE_CATALOG FROM INFORMATION_SCHEMA.COLUMNS; -INSERT INTO t1 SELECT * FROM t1; -INSERT INTO t1 SELECT * FROM t1; -INSERT INTO t1 SELECT * FROM t1; -INSERT INTO t1 SELECT * FROM t1; -INSERT INTO t1 SELECT * FROM t1; +CREATE TABLE t1(a INT) ENGINE=INNODB; +INSERT INTO t1 SELECT 1 FROM seq_1_to_60000; SET @save_use_stat_tables= @@use_stat_tables; SET use_stat_tables= preferably; SELECT count(*) FROM t1; count(*) -54336 -CREATE INDEX idx ON t1(TABLE_CATALOG); -Warnings: -Warning 1071 Specified key was too long; max key length is 767 bytes -ANALYZE TABLE t1 PERSISTENT FOR COLUMNS (TABLE_CATALOG) INDEXES (idx); +60000 +CREATE INDEX idx ON t1(a); +ANALYZE TABLE t1 PERSISTENT FOR COLUMNS (a) INDEXES (idx); Table Op Msg_type Msg_text test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT * FROM mysql.index_stats where table_name='t1'; db_name table_name index_name prefix_arity avg_frequency -test t1 idx 1 NULL +test t1 idx 1 60000.0000 SELECT * FROM mysql.column_stats where table_name='t1'; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 TABLE_CATALOG def def 0.0000 3.0000 54336.0000 0 NULL NULL +test t1 a 1 1 0.0000 4.0000 60000.0000 0 NULL NULL SET use_stat_tables= @save_use_stat_tables; DROP TABLE t1; +# end of 10.1 tests SET SESSION STORAGE_ENGINE=DEFAULT; diff --git a/mysql-test/t/stat_tables_innodb.test b/mysql-test/t/stat_tables_innodb.test index e4a11955aba..008ca6911e9 100644 --- a/mysql-test/t/stat_tables_innodb.test +++ b/mysql-test/t/stat_tables_innodb.test @@ -1,4 +1,5 @@ --source include/have_innodb.inc +--source include/have_sequence.inc SET SESSION STORAGE_ENGINE='InnoDB'; @@ -13,21 +14,19 @@ set optimizer_switch=@save_optimizer_switch_for_stat_tables_test; --echo # MDEV-22851: Engine independent index statistics are incorrect for large tables on Windows. --echo # -CREATE TABLE t1 AS SELECT TABLE_CATALOG FROM INFORMATION_SCHEMA.COLUMNS; -INSERT INTO t1 SELECT * FROM t1; -INSERT INTO t1 SELECT * FROM t1; -INSERT INTO t1 SELECT * FROM t1; -INSERT INTO t1 SELECT * FROM t1; -INSERT INTO t1 SELECT * FROM t1; +CREATE TABLE t1(a INT) ENGINE=INNODB; +INSERT INTO t1 SELECT 1 FROM seq_1_to_60000; SET @save_use_stat_tables= @@use_stat_tables; SET use_stat_tables= preferably; SELECT count(*) FROM t1; -CREATE INDEX idx ON t1(TABLE_CATALOG); -ANALYZE TABLE t1 PERSISTENT FOR COLUMNS (TABLE_CATALOG) INDEXES (idx); +CREATE INDEX idx ON t1(a); +ANALYZE TABLE t1 PERSISTENT FOR COLUMNS (a) INDEXES (idx); SELECT * FROM mysql.index_stats where table_name='t1'; SELECT * FROM mysql.column_stats where table_name='t1'; SET use_stat_tables= @save_use_stat_tables; DROP TABLE t1; +--echo # end of 10.1 tests + SET SESSION STORAGE_ENGINE=DEFAULT; -- cgit v1.2.1 From 14543afd59d7d42a639b6933c404f971c2cc76a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 16 Jul 2020 12:33:20 +0300 Subject: Cleanup: Remove unused AbstractCallback::m_free_limit --- storage/innobase/row/row0import.cc | 9 --------- storage/xtradb/row/row0import.cc | 9 --------- 2 files changed, 18 deletions(-) diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index f5e882f96fe..2121b00d009 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -561,14 +561,6 @@ protected: /** Space id of the file being iterated over. */ ulint m_space; - /** Minimum page number for which the free list has not been - initialized: the pages >= this limit are, by definition, free; - note that in a single-table tablespace where size < 64 pages, - this number is 64, i.e., we have initialized the space about - the first extent, but have not physically allocted those pages - to the file. @see FSP_LIMIT. */ - ulint m_free_limit; - /** Current size of the space in pages */ ulint m_size; @@ -647,7 +639,6 @@ AbstractCallback::init( ut_a(m_space == ULINT_UNDEFINED); m_size = mach_read_from_4(page + FSP_SIZE); - m_free_limit = mach_read_from_4(page + FSP_FREE_LIMIT); m_space = mach_read_from_4(page + FSP_HEADER_OFFSET + FSP_SPACE_ID); return set_current_xdes(0, page); diff --git a/storage/xtradb/row/row0import.cc b/storage/xtradb/row/row0import.cc index f5e882f96fe..2121b00d009 100644 --- a/storage/xtradb/row/row0import.cc +++ b/storage/xtradb/row/row0import.cc @@ -561,14 +561,6 @@ protected: /** Space id of the file being iterated over. */ ulint m_space; - /** Minimum page number for which the free list has not been - initialized: the pages >= this limit are, by definition, free; - note that in a single-table tablespace where size < 64 pages, - this number is 64, i.e., we have initialized the space about - the first extent, but have not physically allocted those pages - to the file. @see FSP_LIMIT. */ - ulint m_free_limit; - /** Current size of the space in pages */ ulint m_size; @@ -647,7 +639,6 @@ AbstractCallback::init( ut_a(m_space == ULINT_UNDEFINED); m_size = mach_read_from_4(page + FSP_SIZE); - m_free_limit = mach_read_from_4(page + FSP_FREE_LIMIT); m_space = mach_read_from_4(page + FSP_HEADER_OFFSET + FSP_SPACE_ID); return set_current_xdes(0, page); -- cgit v1.2.1 From 98e2c17e9e20898bc8c1e58c57e0666502ec447e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 16 Jul 2020 16:31:23 +0300 Subject: Cleanup: Remove fil_check_adress_in_tablespace() --- storage/innobase/buf/buf0dblwr.cc | 14 ++++++++++---- storage/innobase/fil/fil0fil.cc | 21 +-------------------- storage/innobase/include/fil0fil.h | 12 +----------- storage/xtradb/buf/buf0dblwr.cc | 14 ++++++++++---- storage/xtradb/fil/fil0fil.cc | 21 +-------------------- storage/xtradb/include/fil0fil.h | 12 +----------- 6 files changed, 24 insertions(+), 70 deletions(-) diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index 32b4399b41d..8afed48b8c1 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -554,12 +554,18 @@ buf_dblwr_process() continue; } - if (!fil_check_adress_in_tablespace(space_id, page_no)) { + if (!space()->size) { + fil_space_get_size(space_id); + } + + if (UNIV_UNLIKELY(space()->size <= page_no)) { ib_logf(IB_LOG_LEVEL_WARN, - "A copy of page " ULINTPF ":" ULINTPF + "A copy of page " ULINTPF " in the doublewrite buffer slot " ULINTPF - " is not within space bounds", - space_id, page_no, page_no_dblwr); + " is beyond the end of the tablespace " + " %s (" ULINTPF " pages)", + page_no, page_no_dblwr, + space()->name, space()->size); continue; } diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 7234a6c4102..ac48db75624 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2019, MariaDB Corporation. +Copyright (c) 2014, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1775,25 +1775,6 @@ fil_space_get_zip_size( return(flags); } -/*******************************************************************//** -Checks if the pair space, page_no refers to an existing page in a tablespace -file space. The tablespace must be cached in the memory cache. -@return TRUE if the address is meaningful */ -UNIV_INTERN -ibool -fil_check_adress_in_tablespace( -/*===========================*/ - ulint id, /*!< in: space id */ - ulint page_no)/*!< in: page number */ -{ - if (fil_space_get_size(id) > page_no) { - - return(TRUE); - } - - return(FALSE); -} - /****************************************************************//** Initializes the tablespace memory cache. */ UNIV_INTERN diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 4bd394ff94d..448532e249b 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2019, MariaDB Corporation. +Copyright (c) 2013, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -568,16 +568,6 @@ ulint fil_space_get_zip_size( /*===================*/ ulint id); /*!< in: space id */ -/*******************************************************************//** -Checks if the pair space, page_no refers to an existing page in a tablespace -file space. The tablespace must be cached in the memory cache. -@return TRUE if the address is meaningful */ -UNIV_INTERN -ibool -fil_check_adress_in_tablespace( -/*===========================*/ - ulint id, /*!< in: space id */ - ulint page_no);/*!< in: page number */ /****************************************************************//** Initializes the tablespace memory cache. */ UNIV_INTERN diff --git a/storage/xtradb/buf/buf0dblwr.cc b/storage/xtradb/buf/buf0dblwr.cc index 5df40b5f4e8..776e5ab06a2 100644 --- a/storage/xtradb/buf/buf0dblwr.cc +++ b/storage/xtradb/buf/buf0dblwr.cc @@ -554,12 +554,18 @@ buf_dblwr_process() continue; } - if (!fil_check_adress_in_tablespace(space_id, page_no)) { + if (!space()->size) { + fil_space_get_size(space_id); + } + + if (UNIV_UNLIKELY(space()->size <= page_no)) { ib_logf(IB_LOG_LEVEL_WARN, - "A copy of page " ULINTPF ":" ULINTPF + "A copy of page " ULINTPF " in the doublewrite buffer slot " ULINTPF - " is not within space bounds", - space_id, page_no, page_no_dblwr); + " is beyond the end of the tablespace " + " %s (" ULINTPF " pages)", + page_no, page_no_dblwr, + space()->name, space()->size); continue; } diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc index 766e9d91cfb..3c00c857a6d 100644 --- a/storage/xtradb/fil/fil0fil.cc +++ b/storage/xtradb/fil/fil0fil.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2019, MariaDB Corporation. +Copyright (c) 2014, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1815,25 +1815,6 @@ fil_space_get_zip_size( return(flags); } -/*******************************************************************//** -Checks if the pair space, page_no refers to an existing page in a tablespace -file space. The tablespace must be cached in the memory cache. -@return TRUE if the address is meaningful */ -UNIV_INTERN -ibool -fil_check_adress_in_tablespace( -/*===========================*/ - ulint id, /*!< in: space id */ - ulint page_no)/*!< in: page number */ -{ - if (fil_space_get_size(id) > page_no) { - - return(TRUE); - } - - return(FALSE); -} - /****************************************************************//** Initializes the tablespace memory cache. */ UNIV_INTERN diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h index a4274f4d8a6..8831ea2e8cd 100644 --- a/storage/xtradb/include/fil0fil.h +++ b/storage/xtradb/include/fil0fil.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2019, MariaDB Corporation. +Copyright (c) 2013, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -574,16 +574,6 @@ ulint fil_space_get_zip_size( /*===================*/ ulint id); /*!< in: space id */ -/*******************************************************************//** -Checks if the pair space, page_no refers to an existing page in a tablespace -file space. The tablespace must be cached in the memory cache. -@return TRUE if the address is meaningful */ -UNIV_INTERN -ibool -fil_check_adress_in_tablespace( -/*===========================*/ - ulint id, /*!< in: space id */ - ulint page_no);/*!< in: page number */ /****************************************************************//** Initializes the tablespace memory cache. */ UNIV_INTERN -- cgit v1.2.1 From 57ec42bc321dee796ce8e711a4499cd665513009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 17 Jul 2020 15:55:45 +0300 Subject: MDEV-23190 InnoDB data file extension is not crash-safe When InnoDB is extending a data file, it is updating the FSP_SIZE field in the first page of the data file. In commit 8451e09073e8b1a300f177d74a9e3a530776640a (MDEV-11556) we removed a work-around for this bug and made recovery stricter, by making it track changes to FSP_SIZE via redo log records, and extend the data files before any changes are being applied to them. It turns out that the function fsp_fill_free_list() is not crash-safe with respect to this when it is initializing the change buffer bitmap page (page 1, or generally, N*innodb_page_size+1). It uses a separate mini-transaction that is committed (and will be written to the redo log file) before the mini-transaction that actually extended the data file. Hence, recovery can observe a reference to a page that is beyond the current end of the data file. fsp_fill_free_list(): Initialize the change buffer bitmap page in the same mini-transaction. The rest of the changes are fixing a bug that the use of the separate mini-transaction was attempting to work around. Namely, we must ensure that no other thread will access the change buffer bitmap page before our mini-transaction has been committed and all page latches have been released. That is, for read-ahead as well as neighbour flushing, we must avoid accessing pages that might not yet be durably part of the tablespace. fil_space_t::committed_size: The size of the tablespace as persisted by mtr_commit(). fil_space_t::max_page_number_for_io(): Limit the highest page number for I/O batches to committed_size. MTR_MEMO_SPACE_X_LOCK: Replaces MTR_MEMO_X_LOCK for fil_space_t::latch. mtr_x_space_lock(): Replaces mtr_x_lock() for fil_space_t::latch. mtr_memo_slot_release_func(): When releasing MTR_MEMO_SPACE_X_LOCK, copy space->size to space->committed_size. In this way, read-ahead or flushing will never be invoked on pages that do not yet exist according to FSP_SIZE. --- storage/innobase/buf/buf0flu.cc | 9 ++-- storage/innobase/buf/buf0rea.cc | 68 +++++++++++++------------ storage/innobase/fil/fil0fil.cc | 5 +- storage/innobase/fsp/fsp0fsp.cc | 99 +++++++++++++++++-------------------- storage/innobase/ibuf/ibuf0ibuf.cc | 6 +-- storage/innobase/include/fil0fil.h | 11 +++++ storage/innobase/include/mtr0mtr.h | 13 ++++- storage/innobase/include/mtr0mtr.ic | 15 +++++- storage/innobase/mtr/mtr0mtr.cc | 11 +++++ storage/innobase/srv/srv0start.cc | 10 +++- storage/innobase/trx/trx0rseg.cc | 6 +-- storage/innobase/trx/trx0sys.cc | 4 +- storage/xtradb/buf/buf0flu.cc | 9 ++-- storage/xtradb/buf/buf0rea.cc | 65 +++++++++++++----------- storage/xtradb/fil/fil0fil.cc | 5 +- storage/xtradb/fsp/fsp0fsp.cc | 99 +++++++++++++++++-------------------- storage/xtradb/ibuf/ibuf0ibuf.cc | 6 +-- storage/xtradb/include/fil0fil.h | 11 +++++ storage/xtradb/include/mtr0mtr.h | 12 +++++ storage/xtradb/include/mtr0mtr.ic | 15 +++++- storage/xtradb/mtr/mtr0mtr.cc | 11 +++++ storage/xtradb/srv/srv0start.cc | 10 +++- storage/xtradb/trx/trx0rseg.cc | 6 +-- storage/xtradb/trx/trx0sys.cc | 4 +- 24 files changed, 313 insertions(+), 197 deletions(-) diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 1325a938dd6..9df58e760e6 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2019, MariaDB Corporation. +Copyright (c) 2013, 2020, MariaDB Corporation. Copyright (c) 2013, 2014, Fusion-io This program is free software; you can redistribute it and/or modify it under @@ -1241,8 +1241,11 @@ buf_flush_try_neighbors( /* fprintf(stderr, "Flush area: low %lu high %lu\n", low, high); */ #endif - if (high > fil_space_get_size(space)) { - high = fil_space_get_size(space); + if (fil_space_t *s = fil_space_acquire_for_io(space)) { + high = s->max_page_number_for_io(high); + fil_space_release_for_io(s); + } else { + return 0; } ulint count = 0; diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc index 3b4d21f7507..a22b1523608 100644 --- a/storage/innobase/buf/buf0rea.cc +++ b/storage/innobase/buf/buf0rea.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2017, MariaDB Corporation. +Copyright (c) 2015, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -292,19 +292,22 @@ buf_read_ahead_random( return(0); } - /* Remember the tablespace version before we ask te tablespace size - below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we - do not try to read outside the bounds of the tablespace! */ + if (fil_space_t *s = fil_space_acquire_for_io(space)) { + /* Remember the tablespace version along with the + tablespace size: if DISCARD + IMPORT changes the + actual .ibd file meanwhile, we do not try to read + outside the bounds of the tablespace! */ + tablespace_version = s->tablespace_version; - tablespace_version = fil_space_get_version(space); - - low = (offset / buf_read_ahead_random_area) - * buf_read_ahead_random_area; - high = (offset / buf_read_ahead_random_area + 1) - * buf_read_ahead_random_area; - if (high > fil_space_get_size(space)) { + low = (offset / buf_read_ahead_random_area) + * buf_read_ahead_random_area; + high = (offset / buf_read_ahead_random_area + 1) + * buf_read_ahead_random_area; + high = s->max_page_number_for_io(high); - high = fil_space_get_size(space); + fil_space_release_for_io(s); + } else { + return 0; } buf_pool_mutex_enter(buf_pool); @@ -435,22 +438,16 @@ buf_read_page( ulint zip_size, ulint offset) { - ib_int64_t tablespace_version; - ulint count; dberr_t err = DB_SUCCESS; - tablespace_version = fil_space_get_version(space_id); - FilSpace space(space_id, true); if (space()) { - - /* We do the i/o in the synchronous aio mode to save thread - switches: hence TRUE */ - count = buf_read_page_low(&err, true, BUF_READ_ANY_PAGE, space_id, - zip_size, FALSE, - tablespace_version, offset); - + ulint count = buf_read_page_low(&err, /*sync=*/true, + BUF_READ_ANY_PAGE, + space_id, zip_size, FALSE, + space()->tablespace_version, + offset); srv_stats.buf_pool_reads.add(count); } @@ -619,21 +616,30 @@ buf_read_ahead_linear( return(0); } - /* Remember the tablespace version before we ask te tablespace size - below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we - do not try to read outside the bounds of the tablespace! */ + uint32_t space_high_limit = 0; - tablespace_version = fil_space_get_version(space); + if (fil_space_t *s = fil_space_acquire_for_io(space)) { + /* Remember the tablespace version along with the + tablespace size: if DISCARD + IMPORT changes the + actual .ibd file meanwhile, we do not try to read + outside the bounds of the tablespace! */ + tablespace_version = s->tablespace_version; - buf_pool_mutex_enter(buf_pool); + space_high_limit = s->max_page_number_for_io(ULINT_UNDEFINED); - if (high > fil_space_get_size(space)) { - buf_pool_mutex_exit(buf_pool); + fil_space_release_for_io(s); + } else { + return 0; + } + + if (high > space_high_limit) { /* The area is not whole, return */ return(0); } + buf_pool_mutex_enter(buf_pool); + if (buf_pool->n_pend_reads > buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) { buf_pool_mutex_exit(buf_pool); @@ -754,7 +760,7 @@ buf_read_ahead_linear( return(0); } - if (high > fil_space_get_size(space)) { + if (high > space_high_limit) { /* The area is not whole, return */ return(0); diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index ac48db75624..62fb8deaf72 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -676,7 +676,7 @@ fil_node_open_file( #ifdef UNIV_HOTBACKUP add_size: #endif /* UNIV_HOTBACKUP */ - space->size += node->size; + space->committed_size = space->size += node->size; } ulint atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(space->flags); @@ -1151,6 +1151,9 @@ retry: ut_a(success); /* InnoDB data files cannot shrink. */ ut_a(space->size >= size); + if (size > space->committed_size) { + space->committed_size = size; + } /* There could be multiple concurrent I/O requests for this tablespace (multiple threads trying to extend diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 13ac923eb3f..3796ab6d144 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -447,7 +447,7 @@ xdes_get_descriptor_with_space_hdr( page_t* descr_page; ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL), - MTR_MEMO_X_LOCK)); + MTR_MEMO_SPACE_X_LOCK)); ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX)); ut_ad(page_offset(sp_header) == FSP_HEADER_OFFSET); /* Read free limit and space size */ @@ -531,7 +531,7 @@ xdes_lst_get_descriptor( ut_ad(mtr); ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL), - MTR_MEMO_X_LOCK)); + MTR_MEMO_SPACE_X_LOCK)); descr = fut_get_ptr(space, zip_size, lst_node, RW_X_LATCH, mtr) - XDES_FLST_NODE; @@ -687,7 +687,7 @@ fsp_header_init(ulint space_id, ulint size, mtr_t* mtr) ut_ad(mtr); - mtr_x_lock(fil_space_get_latch(space_id, &flags), mtr); + mtr_x_space_lock(fil_space_get_latch(space_id, &flags), mtr); zip_size = fsp_flags_get_zip_size(flags); block = buf_page_create(space_id, 0, zip_size, mtr); @@ -814,7 +814,7 @@ fsp_header_inc_size( ut_ad(mtr); - mtr_x_lock(fil_space_get_latch(space, &flags), mtr); + mtr_x_space_lock(fil_space_get_latch(space, &flags), mtr); header = fsp_get_space_header(space, fsp_flags_get_zip_size(flags), @@ -843,7 +843,7 @@ fsp_header_get_tablespace_size(void) mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(0, NULL), &mtr); + mtr_x_space_lock(fil_space_get_latch(0, NULL), &mtr); header = fsp_get_space_header(0, 0, &mtr); @@ -1070,7 +1070,6 @@ fsp_fill_free_list( ulint frag_n_used; ulint actual_increase; ulint i; - mtr_t ibuf_mtr; ut_ad(page_offset(header) == FSP_HEADER_OFFSET); @@ -1138,26 +1137,17 @@ fsp_fill_free_list( MLOG_2BYTES, mtr); } - /* Initialize the ibuf bitmap page in a separate - mini-transaction because it is low in the latching - order, and we must be able to release its latch - before returning from the fsp routine */ - - mtr_start(&ibuf_mtr); - block = buf_page_create(space, - i + FSP_IBUF_BITMAP_OFFSET, - zip_size, &ibuf_mtr); + i + FSP_IBUF_BITMAP_OFFSET, + zip_size, mtr); buf_page_get(space, zip_size, i + FSP_IBUF_BITMAP_OFFSET, - RW_X_LATCH, &ibuf_mtr); + RW_X_LATCH, mtr); buf_block_dbg_add_level(block, SYNC_FSP_PAGE); - fsp_init_file_page(block, &ibuf_mtr); + fsp_init_file_page(block, mtr); - ibuf_bitmap_page_init(block, &ibuf_mtr); - - mtr_commit(&ibuf_mtr); + ibuf_bitmap_page_init(block, mtr); } descr = xdes_get_descriptor_with_space_hdr(header, space, i, @@ -2038,7 +2028,7 @@ fseg_create_general( header = byte_offset + buf_block_get_frame(block); } - mtr_x_lock(latch, mtr); + mtr_x_space_lock(latch, mtr); if (!has_done_reservation) { success = fsp_reserve_free_extents(&n_reserved, space, 2, @@ -2185,7 +2175,7 @@ fseg_n_reserved_pages( latch = fil_space_get_latch(space, &flags); zip_size = fsp_flags_get_zip_size(flags); - mtr_x_lock(latch, mtr); + mtr_x_space_lock(latch, mtr); inode = fseg_inode_get(header, space, zip_size, mtr); @@ -2608,7 +2598,7 @@ fseg_alloc_free_page_general( zip_size = fsp_flags_get_zip_size(flags); - mtr_x_lock(latch, mtr); + mtr_x_space_lock(latch, mtr); inode = fseg_inode_get(seg_header, space, zip_size, mtr); @@ -2725,7 +2715,7 @@ fsp_reserve_free_extents( latch = fil_space_get_latch(space, &flags); zip_size = fsp_flags_get_zip_size(flags); - mtr_x_lock(latch, mtr); + mtr_x_space_lock(latch, mtr); space_header = fsp_get_space_header(space, zip_size, mtr); try_again: @@ -2865,7 +2855,7 @@ fsp_get_available_space_in_free_extents( zip_size = fsp_flags_get_zip_size(flags); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); mutex_exit(&dict_sys->mutex); @@ -3155,7 +3145,7 @@ fseg_free_page( latch = fil_space_get_latch(space, &flags); zip_size = fsp_flags_get_zip_size(flags); - mtr_x_lock(latch, mtr); + mtr_x_space_lock(latch, mtr); seg_inode = fseg_inode_get(seg_header, space, zip_size, mtr); @@ -3189,7 +3179,7 @@ fseg_page_is_free( zip_size = dict_tf_get_zip_size(flags); mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); seg_inode = fseg_inode_get(seg_header, space, zip_size, &mtr); @@ -3314,7 +3304,7 @@ fseg_free_step( latch = fil_space_get_latch(space, &flags); zip_size = fsp_flags_get_zip_size(flags); - mtr_x_lock(latch, mtr); + mtr_x_space_lock(latch, mtr); descr = xdes_get_descriptor(space, zip_size, header_page, mtr); @@ -3395,7 +3385,7 @@ fseg_free_step_not_header( latch = fil_space_get_latch(space, &flags); zip_size = fsp_flags_get_zip_size(flags); - mtr_x_lock(latch, mtr); + mtr_x_space_lock(latch, mtr); inode = fseg_inode_get(header, space, zip_size, mtr); @@ -3515,7 +3505,7 @@ fseg_validate_low( ulint zip_size; mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space, &flags), &mtr); + mtr_x_space_lock(fil_space_get_latch(space, &flags), &mtr); zip_size = fsp_flags_get_zip_size(flags); descr = xdes_lst_get_descriptor(space, zip_size, @@ -3538,7 +3528,7 @@ fseg_validate_low( ulint zip_size; mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space, &flags), &mtr); + mtr_x_space_lock(fil_space_get_latch(space, &flags), &mtr); zip_size = fsp_flags_get_zip_size(flags); descr = xdes_lst_get_descriptor(space, zip_size, @@ -3564,7 +3554,7 @@ fseg_validate_low( ulint zip_size; mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space, &flags), &mtr); + mtr_x_space_lock(fil_space_get_latch(space, &flags), &mtr); zip_size = fsp_flags_get_zip_size(flags); descr = xdes_lst_get_descriptor(space, zip_size, @@ -3602,7 +3592,7 @@ fseg_validate( space = page_get_space_id(page_align(header)); - mtr_x_lock(fil_space_get_latch(space, &flags), mtr); + mtr_x_space_lock(fil_space_get_latch(space, &flags), mtr); zip_size = fsp_flags_get_zip_size(flags); inode = fseg_inode_get(header, space, zip_size, mtr); @@ -3678,7 +3668,7 @@ fseg_print( space = page_get_space_id(page_align(header)); - mtr_x_lock(fil_space_get_latch(space, &flags), mtr); + mtr_x_space_lock(fil_space_get_latch(space, &flags), mtr); zip_size = fsp_flags_get_zip_size(flags); inode = fseg_inode_get(header, space, zip_size, mtr); @@ -3727,10 +3717,10 @@ fsp_validate( /* Start first a mini-transaction mtr2 to lock out all other threads from the fsp system */ mtr_start(&mtr2); - mtr_x_lock(latch, &mtr2); + mtr_x_space_lock(latch, &mtr2); mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); header = fsp_get_space_header(space, zip_size, &mtr); @@ -3757,7 +3747,7 @@ fsp_validate( /* Validate FSP_FREE list */ mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); header = fsp_get_space_header(space, zip_size, &mtr); node_addr = flst_get_first(header + FSP_FREE, &mtr); @@ -3766,7 +3756,7 @@ fsp_validate( while (!fil_addr_is_null(node_addr)) { mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); descr_count++; descr = xdes_lst_get_descriptor(space, zip_size, @@ -3781,7 +3771,7 @@ fsp_validate( /* Validate FSP_FREE_FRAG list */ mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); header = fsp_get_space_header(space, zip_size, &mtr); node_addr = flst_get_first(header + FSP_FREE_FRAG, &mtr); @@ -3790,7 +3780,7 @@ fsp_validate( while (!fil_addr_is_null(node_addr)) { mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); descr_count++; descr = xdes_lst_get_descriptor(space, zip_size, @@ -3808,7 +3798,7 @@ fsp_validate( /* Validate FSP_FULL_FRAG list */ mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); header = fsp_get_space_header(space, zip_size, &mtr); node_addr = flst_get_first(header + FSP_FULL_FRAG, &mtr); @@ -3817,7 +3807,7 @@ fsp_validate( while (!fil_addr_is_null(node_addr)) { mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); descr_count++; descr = xdes_lst_get_descriptor(space, zip_size, @@ -3832,7 +3822,7 @@ fsp_validate( /* Validate segments */ mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); header = fsp_get_space_header(space, zip_size, &mtr); @@ -3847,7 +3837,7 @@ fsp_validate( n = 0; do { mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); seg_inode_page = fut_get_ptr( space, zip_size, node_addr, RW_X_LATCH, &mtr) @@ -3876,7 +3866,7 @@ fsp_validate( } mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); header = fsp_get_space_header(space, zip_size, &mtr); @@ -3892,7 +3882,7 @@ fsp_validate( do { mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); seg_inode_page = fut_get_ptr( space, zip_size, node_addr, RW_X_LATCH, &mtr) @@ -3976,11 +3966,11 @@ fsp_print( mtr_start(&mtr2); - mtr_x_lock(latch, &mtr2); + mtr_x_space_lock(latch, &mtr2); mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); header = fsp_get_space_header(space, zip_size, &mtr); @@ -4012,7 +4002,7 @@ fsp_print( /* Print segments */ mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); header = fsp_get_space_header(space, zip_size, &mtr); @@ -4027,7 +4017,7 @@ fsp_print( do { mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); seg_inode_page = fut_get_ptr( space, zip_size, node_addr, RW_X_LATCH, &mtr) @@ -4049,7 +4039,7 @@ fsp_print( } mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); header = fsp_get_space_header(space, zip_size, &mtr); @@ -4064,7 +4054,7 @@ fsp_print( do { mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); seg_inode_page = fut_get_ptr( space, zip_size, node_addr, RW_X_LATCH, &mtr) @@ -4121,7 +4111,8 @@ fsp_page_is_free_func( ut_ad(mtr); - mtr_x_lock_func(fil_space_get_latch(space, &flags), file, line, mtr); + mtr_x_space_lock_func(fil_space_get_latch(space, &flags), file, line, + mtr); ulint zip_size = fsp_flags_get_zip_size(flags); xdes_t* descr = xdes_get_descriptor(space, zip_size, page_no, mtr); diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index 086fb3427c8..9427ade1ce4 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -548,7 +548,7 @@ ibuf_init_at_db_start(void) mutex_enter(&ibuf_mutex); - mtr_x_lock(fil_space_get_latch(IBUF_SPACE_ID, NULL), &mtr); + mtr_x_space_lock(fil_space_get_latch(IBUF_SPACE_ID, NULL), &mtr); header_page = ibuf_header_page_get(&mtr); @@ -2098,7 +2098,7 @@ ibuf_add_free_page(void) /* Acquire the fsp latch before the ibuf header, obeying the latching order */ - mtr_x_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr); + mtr_x_space_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr); zip_size = fsp_flags_get_zip_size(flags); header_page = ibuf_header_page_get(&mtr); @@ -2182,7 +2182,7 @@ ibuf_remove_free_page(void) /* Acquire the fsp latch before the ibuf header, obeying the latching order */ - mtr_x_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr); + mtr_x_space_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr); zip_size = fsp_flags_get_zip_size(flags); header_page = ibuf_header_page_get(&mtr); diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 448532e249b..5b11a026cf9 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -306,6 +306,8 @@ struct fil_space_t { /*!< recovered tablespace size in pages; 0 if no size change was read from the redo log, or if the size change was implemented */ + /** the committed size of the tablespace in pages */ + ulint committed_size; ulint flags; /*!< FSP_SPACE_FLAGS and FSP_FLAGS_MEM_ flags; see fsp0fsp.h, fsp_flags_is_valid(), @@ -365,6 +367,15 @@ struct fil_space_t { { return stop_new_ops; } + + /** Clamp a page number for batched I/O, such as read-ahead. + @param offset page number limit + @return offset clamped to the tablespace size */ + ulint max_page_number_for_io(ulint offset) const + { + const ulint limit= committed_size; + return limit > offset ? offset : limit; + } }; /** Value of fil_space_t::magic_n */ diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h index 6c0ee2c7ac7..d28c52237b2 100644 --- a/storage/innobase/include/mtr0mtr.h +++ b/storage/innobase/include/mtr0mtr.h @@ -2,7 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2016, MariaDB Corporation +Copyright (c) 2013, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -58,6 +58,7 @@ first 3 values must be RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */ #endif /* UNIV_DEBUG */ #define MTR_MEMO_S_LOCK 55 #define MTR_MEMO_X_LOCK 56 +#define MTR_MEMO_SPACE_X_LOCK 57 /** @name Log item types The log items are declared 'byte' so that the compiler can warn if val @@ -295,6 +296,8 @@ This macro locks an rw-lock in s-mode. */ This macro locks an rw-lock in x-mode. */ #define mtr_x_lock(B, MTR) mtr_x_lock_func((B), __FILE__, __LINE__,\ (MTR)) +#define mtr_x_space_lock(B, MTR) mtr_x_space_lock_func(B, __FILE__, __LINE__,\ + MTR) /*********************************************************************//** NOTE! Use the macro above! Locks a lock in s-mode. */ @@ -317,6 +320,14 @@ mtr_x_lock_func( const char* file, /*!< in: file name */ ulint line, /*!< in: line number */ mtr_t* mtr); /*!< in: mtr */ + +/** Acquire exclusive tablespace latch. +@param lock fil_space_t::latch +@param file source code file name of the caller +@param line source code line number of the caller +@param mtr mini-transaction */ +inline void mtr_x_space_lock_func(rw_lock_t *lock, + const char *file, ulint line, mtr_t *mtr); #endif /* !UNIV_HOTBACKUP */ /***************************************************//** diff --git a/storage/innobase/include/mtr0mtr.ic b/storage/innobase/include/mtr0mtr.ic index 5763c054a8f..a0f4779fb10 100644 --- a/storage/innobase/include/mtr0mtr.ic +++ b/storage/innobase/include/mtr0mtr.ic @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -78,7 +79,7 @@ mtr_memo_push( ut_ad(object); ut_ad(type >= MTR_MEMO_PAGE_S_FIX); - ut_ad(type <= MTR_MEMO_X_LOCK); + ut_ad(type <= MTR_MEMO_SPACE_X_LOCK); ut_ad(mtr); ut_ad(mtr->magic_n == MTR_MAGIC_N); ut_ad(mtr->state == MTR_ACTIVE); @@ -293,4 +294,16 @@ mtr_x_lock_func( mtr_memo_push(mtr, lock, MTR_MEMO_X_LOCK); } + +/** Acquire exclusive tablespace latch. +@param lock fil_space_t::latch +@param file source code file name of the caller +@param line source code line number of the caller +@param mtr mini-transaction */ +inline void mtr_x_space_lock_func(rw_lock_t *lock, + const char *file, ulint line, mtr_t *mtr) +{ + rw_lock_x_lock_inline(lock, 0, file, line); + mtr_memo_push(mtr, lock, MTR_MEMO_SPACE_X_LOCK); +} #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index 2db6e62cbed..1388da713b0 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -87,6 +88,16 @@ mtr_memo_slot_release_func( case MTR_MEMO_X_LOCK: rw_lock_x_unlock((rw_lock_t*) object); break; + case MTR_MEMO_SPACE_X_LOCK: + { + fil_space_t* space = reinterpret_cast( + static_cast(object) + - reinterpret_cast( + &static_cast(0)->latch)); + space->committed_size = space->size; + rw_lock_x_unlock(&space->latch); + } + break; #ifdef UNIV_DEBUG default: ut_ad(slot->type == MTR_MEMO_MODIFY); diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index a73e67e9f5b..05f29d60411 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -3,7 +3,7 @@ Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2019, MariaDB Corporation. +Copyright (c) 2013, 2020, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1203,6 +1203,10 @@ check_first_page: } } + if (fil_space_t* s = fil_space_get(0)) { + s->committed_size = s->size; + } + return(DB_SUCCESS); } @@ -1371,6 +1375,10 @@ srv_undo_tablespace_open( if (fil_node_create(name, (ulint) n_pages, space, FALSE)) { err = DB_SUCCESS; } + + if (fil_space_t* s = fil_space_get(space)) { + s->committed_size = n_pages; + } } return(err); diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc index 944e2353de8..e73e20737f6 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -65,7 +65,7 @@ trx_rseg_header_create( ut_ad(mtr); ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL), - MTR_MEMO_X_LOCK)); + MTR_MEMO_SPACE_X_LOCK)); /* Allocate a new file segment for the rollback segment */ block = fseg_create(space, 0, TRX_RSEG + TRX_RSEG_FSEG_HEADER, mtr); @@ -310,7 +310,7 @@ trx_rseg_create(ulint space) /* To obey the latching order, acquire the file space x-latch before the trx_sys->mutex. */ - mtr_x_lock(fil_space_get_latch(space, NULL), &mtr); + mtr_x_space_lock(fil_space_get_latch(space, NULL), &mtr); slot_no = trx_sysf_rseg_find_free(&mtr); diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc index 13fd37f4e50..6f348a2b13e 100644 --- a/storage/innobase/trx/trx0sys.cc +++ b/storage/innobase/trx/trx0sys.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -550,7 +550,7 @@ trx_sysf_create( then enter the kernel: we must do it in this order to conform to the latching order rules. */ - mtr_x_lock(fil_space_get_latch(TRX_SYS_SPACE, NULL), mtr); + mtr_x_space_lock(fil_space_get_latch(TRX_SYS_SPACE, NULL), mtr); /* Create the trx sys file block in a new allocated file segment */ block = fseg_create(TRX_SYS_SPACE, 0, TRX_SYS + TRX_SYS_FSEG_HEADER, diff --git a/storage/xtradb/buf/buf0flu.cc b/storage/xtradb/buf/buf0flu.cc index eccc7c281c1..4993654952b 100644 --- a/storage/xtradb/buf/buf0flu.cc +++ b/storage/xtradb/buf/buf0flu.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2019, MariaDB Corporation. +Copyright (c) 2013, 2020, MariaDB Corporation. Copyright (c) 2013, 2014, Fusion-io This program is free software; you can redistribute it and/or modify it under @@ -1297,8 +1297,11 @@ buf_flush_try_neighbors( /* fprintf(stderr, "Flush area: low %lu high %lu\n", low, high); */ - if (high > fil_space_get_size(space)) { - high = fil_space_get_size(space); + if (fil_space_t *s = fil_space_acquire_for_io(space)) { + high = s->max_page_number_for_io(high); + fil_space_release_for_io(s); + } else { + return 0; } ulint count = 0; diff --git a/storage/xtradb/buf/buf0rea.cc b/storage/xtradb/buf/buf0rea.cc index 1ef9162cab9..a962b94c0c2 100644 --- a/storage/xtradb/buf/buf0rea.cc +++ b/storage/xtradb/buf/buf0rea.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -344,19 +344,22 @@ buf_read_ahead_random( return(0); } - /* Remember the tablespace version before we ask te tablespace size - below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we - do not try to read outside the bounds of the tablespace! */ + if (fil_space_t *s = fil_space_acquire_for_io(space)) { + /* Remember the tablespace version along with the + tablespace size: if DISCARD + IMPORT changes the + actual .ibd file meanwhile, we do not try to read + outside the bounds of the tablespace! */ + tablespace_version = s->tablespace_version; - tablespace_version = fil_space_get_version(space); - - low = (offset / buf_read_ahead_random_area) - * buf_read_ahead_random_area; - high = (offset / buf_read_ahead_random_area + 1) - * buf_read_ahead_random_area; - if (high > fil_space_get_size(space)) { + low = (offset / buf_read_ahead_random_area) + * buf_read_ahead_random_area; + high = (offset / buf_read_ahead_random_area + 1) + * buf_read_ahead_random_area; + high = s->max_page_number_for_io(high); - high = fil_space_get_size(space); + fil_space_release_for_io(s); + } else { + return 0; } if (buf_pool->n_pend_reads @@ -495,22 +498,16 @@ buf_read_page( ulint offset, trx_t* trx) { - ib_int64_t tablespace_version; - ulint count; dberr_t err = DB_SUCCESS; - tablespace_version = fil_space_get_version(space_id); - FilSpace space(space_id, true); if (space()) { - - /* We do the i/o in the synchronous aio mode to save thread - switches: hence TRUE */ - count = buf_read_page_low(&err, true, BUF_READ_ANY_PAGE, space_id, - zip_size, FALSE, - tablespace_version, offset, trx); - + ulint count = buf_read_page_low(&err, /*sync=*/true, + BUF_READ_ANY_PAGE, + space_id, zip_size, FALSE, + space()->tablespace_version, + offset, trx); srv_stats.buf_pool_reads.add(count); } @@ -683,13 +680,23 @@ buf_read_ahead_linear( return(0); } - /* Remember the tablespace version before we ask te tablespace size - below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we - do not try to read outside the bounds of the tablespace! */ + uint32_t space_high_limit = 0; - tablespace_version = fil_space_get_version(space); + if (fil_space_t *s = fil_space_acquire_for_io(space)) { + /* Remember the tablespace version along with the + tablespace size: if DISCARD + IMPORT changes the + actual .ibd file meanwhile, we do not try to read + outside the bounds of the tablespace! */ + tablespace_version = s->tablespace_version; + + space_high_limit = s->max_page_number_for_io(ULINT_UNDEFINED); + + fil_space_release_for_io(s); + } else { + return 0; + } - if (high > fil_space_get_size(space)) { + if (high > space_high_limit) { /* The area is not whole, return */ return(0); @@ -825,7 +832,7 @@ buf_read_ahead_linear( return(0); } - if (high > fil_space_get_size(space)) { + if (high > space_high_limit) { /* The area is not whole, return */ return(0); diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc index 3c00c857a6d..b5ccb533af8 100644 --- a/storage/xtradb/fil/fil0fil.cc +++ b/storage/xtradb/fil/fil0fil.cc @@ -684,7 +684,7 @@ fil_node_open_file( #ifdef UNIV_HOTBACKUP add_size: #endif /* UNIV_HOTBACKUP */ - space->size += node->size; + space->committed_size = space->size += node->size; } ulint atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(space->flags); @@ -1158,6 +1158,9 @@ retry: ut_a(success); /* InnoDB data files cannot shrink. */ ut_a(space->size >= size); + if (size > space->committed_size) { + space->committed_size = size; + } /* There could be multiple concurrent I/O requests for this tablespace (multiple threads trying to extend diff --git a/storage/xtradb/fsp/fsp0fsp.cc b/storage/xtradb/fsp/fsp0fsp.cc index fc2e192a3b1..e2e9709d5f2 100644 --- a/storage/xtradb/fsp/fsp0fsp.cc +++ b/storage/xtradb/fsp/fsp0fsp.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -450,7 +450,7 @@ xdes_get_descriptor_with_space_hdr( page_t* descr_page; ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL), - MTR_MEMO_X_LOCK)); + MTR_MEMO_SPACE_X_LOCK)); ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX)); ut_ad(page_offset(sp_header) == FSP_HEADER_OFFSET); /* Read free limit and space size */ @@ -534,7 +534,7 @@ xdes_lst_get_descriptor( ut_ad(mtr); ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL), - MTR_MEMO_X_LOCK)); + MTR_MEMO_SPACE_X_LOCK)); descr = fut_get_ptr(space, zip_size, lst_node, RW_X_LATCH, mtr) - XDES_FLST_NODE; @@ -690,7 +690,7 @@ fsp_header_init(ulint space_id, ulint size, mtr_t* mtr) ut_ad(mtr); - mtr_x_lock(fil_space_get_latch(space_id, &flags), mtr); + mtr_x_space_lock(fil_space_get_latch(space_id, &flags), mtr); zip_size = fsp_flags_get_zip_size(flags); block = buf_page_create(space_id, 0, zip_size, mtr); @@ -817,7 +817,7 @@ fsp_header_inc_size( ut_ad(mtr); - mtr_x_lock(fil_space_get_latch(space, &flags), mtr); + mtr_x_space_lock(fil_space_get_latch(space, &flags), mtr); header = fsp_get_space_header(space, fsp_flags_get_zip_size(flags), @@ -846,7 +846,7 @@ fsp_header_get_tablespace_size(void) mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(0, NULL), &mtr); + mtr_x_space_lock(fil_space_get_latch(0, NULL), &mtr); header = fsp_get_space_header(0, 0, &mtr); @@ -1073,7 +1073,6 @@ fsp_fill_free_list( ulint frag_n_used; ulint actual_increase; ulint i; - mtr_t ibuf_mtr; ut_ad(page_offset(header) == FSP_HEADER_OFFSET); @@ -1141,26 +1140,17 @@ fsp_fill_free_list( MLOG_2BYTES, mtr); } - /* Initialize the ibuf bitmap page in a separate - mini-transaction because it is low in the latching - order, and we must be able to release its latch - before returning from the fsp routine */ - - mtr_start(&ibuf_mtr); - block = buf_page_create(space, - i + FSP_IBUF_BITMAP_OFFSET, - zip_size, &ibuf_mtr); + i + FSP_IBUF_BITMAP_OFFSET, + zip_size, mtr); buf_page_get(space, zip_size, i + FSP_IBUF_BITMAP_OFFSET, - RW_X_LATCH, &ibuf_mtr); + RW_X_LATCH, mtr); buf_block_dbg_add_level(block, SYNC_FSP_PAGE); - fsp_init_file_page(block, &ibuf_mtr); + fsp_init_file_page(block, mtr); - ibuf_bitmap_page_init(block, &ibuf_mtr); - - mtr_commit(&ibuf_mtr); + ibuf_bitmap_page_init(block, mtr); } descr = xdes_get_descriptor_with_space_hdr(header, space, i, @@ -2047,7 +2037,7 @@ fseg_create_general( header = byte_offset + buf_block_get_frame(block); } - mtr_x_lock(latch, mtr); + mtr_x_space_lock(latch, mtr); if (!has_done_reservation) { success = fsp_reserve_free_extents(&n_reserved, space, 2, @@ -2194,7 +2184,7 @@ fseg_n_reserved_pages( latch = fil_space_get_latch(space, &flags); zip_size = fsp_flags_get_zip_size(flags); - mtr_x_lock(latch, mtr); + mtr_x_space_lock(latch, mtr); inode = fseg_inode_get(header, space, zip_size, mtr); @@ -2617,7 +2607,7 @@ fseg_alloc_free_page_general( zip_size = fsp_flags_get_zip_size(flags); - mtr_x_lock(latch, mtr); + mtr_x_space_lock(latch, mtr); inode = fseg_inode_get(seg_header, space, zip_size, mtr); @@ -2734,7 +2724,7 @@ fsp_reserve_free_extents( latch = fil_space_get_latch(space, &flags); zip_size = fsp_flags_get_zip_size(flags); - mtr_x_lock(latch, mtr); + mtr_x_space_lock(latch, mtr); space_header = fsp_get_space_header(space, zip_size, mtr); try_again: @@ -2873,7 +2863,7 @@ fsp_get_available_space_in_free_extents( zip_size = fsp_flags_get_zip_size(flags); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); mutex_exit(&dict_sys->mutex); @@ -3169,7 +3159,7 @@ fseg_free_page( latch = fil_space_get_latch(space, &flags); zip_size = fsp_flags_get_zip_size(flags); - mtr_x_lock(latch, mtr); + mtr_x_space_lock(latch, mtr); seg_inode = fseg_inode_get(seg_header, space, zip_size, mtr); @@ -3203,7 +3193,7 @@ fseg_page_is_free( zip_size = dict_tf_get_zip_size(flags); mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); seg_inode = fseg_inode_get(seg_header, space, zip_size, &mtr); @@ -3328,7 +3318,7 @@ fseg_free_step( latch = fil_space_get_latch(space, &flags); zip_size = fsp_flags_get_zip_size(flags); - mtr_x_lock(latch, mtr); + mtr_x_space_lock(latch, mtr); descr = xdes_get_descriptor(space, zip_size, header_page, mtr); @@ -3415,7 +3405,7 @@ fseg_free_step_not_header( latch = fil_space_get_latch(space, &flags); zip_size = fsp_flags_get_zip_size(flags); - mtr_x_lock(latch, mtr); + mtr_x_space_lock(latch, mtr); inode = fseg_inode_get(header, space, zip_size, mtr); @@ -3541,7 +3531,7 @@ fseg_validate_low( ulint zip_size; mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space, &flags), &mtr); + mtr_x_space_lock(fil_space_get_latch(space, &flags), &mtr); zip_size = fsp_flags_get_zip_size(flags); descr = xdes_lst_get_descriptor(space, zip_size, @@ -3564,7 +3554,7 @@ fseg_validate_low( ulint zip_size; mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space, &flags), &mtr); + mtr_x_space_lock(fil_space_get_latch(space, &flags), &mtr); zip_size = fsp_flags_get_zip_size(flags); descr = xdes_lst_get_descriptor(space, zip_size, @@ -3590,7 +3580,7 @@ fseg_validate_low( ulint zip_size; mtr_start(&mtr); - mtr_x_lock(fil_space_get_latch(space, &flags), &mtr); + mtr_x_space_lock(fil_space_get_latch(space, &flags), &mtr); zip_size = fsp_flags_get_zip_size(flags); descr = xdes_lst_get_descriptor(space, zip_size, @@ -3628,7 +3618,7 @@ fseg_validate( space = page_get_space_id(page_align(header)); - mtr_x_lock(fil_space_get_latch(space, &flags), mtr); + mtr_x_space_lock(fil_space_get_latch(space, &flags), mtr); zip_size = fsp_flags_get_zip_size(flags); inode = fseg_inode_get(header, space, zip_size, mtr); @@ -3704,7 +3694,7 @@ fseg_print( space = page_get_space_id(page_align(header)); - mtr_x_lock(fil_space_get_latch(space, &flags), mtr); + mtr_x_space_lock(fil_space_get_latch(space, &flags), mtr); zip_size = fsp_flags_get_zip_size(flags); inode = fseg_inode_get(header, space, zip_size, mtr); @@ -3753,10 +3743,10 @@ fsp_validate( /* Start first a mini-transaction mtr2 to lock out all other threads from the fsp system */ mtr_start(&mtr2); - mtr_x_lock(latch, &mtr2); + mtr_x_space_lock(latch, &mtr2); mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); header = fsp_get_space_header(space, zip_size, &mtr); @@ -3783,7 +3773,7 @@ fsp_validate( /* Validate FSP_FREE list */ mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); header = fsp_get_space_header(space, zip_size, &mtr); node_addr = flst_get_first(header + FSP_FREE, &mtr); @@ -3792,7 +3782,7 @@ fsp_validate( while (!fil_addr_is_null(node_addr)) { mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); descr_count++; descr = xdes_lst_get_descriptor(space, zip_size, @@ -3807,7 +3797,7 @@ fsp_validate( /* Validate FSP_FREE_FRAG list */ mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); header = fsp_get_space_header(space, zip_size, &mtr); node_addr = flst_get_first(header + FSP_FREE_FRAG, &mtr); @@ -3816,7 +3806,7 @@ fsp_validate( while (!fil_addr_is_null(node_addr)) { mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); descr_count++; descr = xdes_lst_get_descriptor(space, zip_size, @@ -3834,7 +3824,7 @@ fsp_validate( /* Validate FSP_FULL_FRAG list */ mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); header = fsp_get_space_header(space, zip_size, &mtr); node_addr = flst_get_first(header + FSP_FULL_FRAG, &mtr); @@ -3843,7 +3833,7 @@ fsp_validate( while (!fil_addr_is_null(node_addr)) { mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); descr_count++; descr = xdes_lst_get_descriptor(space, zip_size, @@ -3858,7 +3848,7 @@ fsp_validate( /* Validate segments */ mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); header = fsp_get_space_header(space, zip_size, &mtr); @@ -3873,7 +3863,7 @@ fsp_validate( n = 0; do { mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); seg_inode_page = fut_get_ptr( space, zip_size, node_addr, RW_X_LATCH, &mtr) @@ -3902,7 +3892,7 @@ fsp_validate( } mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); header = fsp_get_space_header(space, zip_size, &mtr); @@ -3918,7 +3908,7 @@ fsp_validate( do { mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); seg_inode_page = fut_get_ptr( space, zip_size, node_addr, RW_X_LATCH, &mtr) @@ -4002,11 +3992,11 @@ fsp_print( mtr_start(&mtr2); - mtr_x_lock(latch, &mtr2); + mtr_x_space_lock(latch, &mtr2); mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); header = fsp_get_space_header(space, zip_size, &mtr); @@ -4038,7 +4028,7 @@ fsp_print( /* Print segments */ mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); header = fsp_get_space_header(space, zip_size, &mtr); @@ -4053,7 +4043,7 @@ fsp_print( do { mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); seg_inode_page = fut_get_ptr( space, zip_size, node_addr, RW_X_LATCH, &mtr) @@ -4075,7 +4065,7 @@ fsp_print( } mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); header = fsp_get_space_header(space, zip_size, &mtr); @@ -4090,7 +4080,7 @@ fsp_print( do { mtr_start(&mtr); - mtr_x_lock(latch, &mtr); + mtr_x_space_lock(latch, &mtr); seg_inode_page = fut_get_ptr( space, zip_size, node_addr, RW_X_LATCH, &mtr) @@ -4147,7 +4137,8 @@ fsp_page_is_free_func( ut_ad(mtr); - mtr_x_lock_func(fil_space_get_latch(space, &flags), file, line, mtr); + mtr_x_space_lock_func(fil_space_get_latch(space, &flags), file, line, + mtr); ulint zip_size = fsp_flags_get_zip_size(flags); xdes_t* descr = xdes_get_descriptor(space, zip_size, page_no, mtr); diff --git a/storage/xtradb/ibuf/ibuf0ibuf.cc b/storage/xtradb/ibuf/ibuf0ibuf.cc index cd65ea15729..6f11daa7363 100644 --- a/storage/xtradb/ibuf/ibuf0ibuf.cc +++ b/storage/xtradb/ibuf/ibuf0ibuf.cc @@ -588,7 +588,7 @@ ibuf_init_at_db_start(void) mutex_enter(&ibuf_mutex); - mtr_x_lock(fil_space_get_latch(IBUF_SPACE_ID, NULL), &mtr); + mtr_x_space_lock(fil_space_get_latch(IBUF_SPACE_ID, NULL), &mtr); header_page = ibuf_header_page_get(&mtr); @@ -2139,7 +2139,7 @@ ibuf_add_free_page(void) /* Acquire the fsp latch before the ibuf header, obeying the latching order */ - mtr_x_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr); + mtr_x_space_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr); zip_size = fsp_flags_get_zip_size(flags); header_page = ibuf_header_page_get(&mtr); @@ -2223,7 +2223,7 @@ ibuf_remove_free_page(void) /* Acquire the fsp latch before the ibuf header, obeying the latching order */ - mtr_x_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr); + mtr_x_space_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr); zip_size = fsp_flags_get_zip_size(flags); header_page = ibuf_header_page_get(&mtr); diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h index 8831ea2e8cd..6a823e131ac 100644 --- a/storage/xtradb/include/fil0fil.h +++ b/storage/xtradb/include/fil0fil.h @@ -300,6 +300,8 @@ struct fil_space_t { /*!< recovered tablespace size in pages; 0 if no size change was read from the redo log, or if the size change was implemented */ + /** the committed size of the tablespace in pages */ + ulint committed_size; ulint flags; /*!< FSP_SPACE_FLAGS and FSP_FLAGS_MEM_ flags; see fsp0fsp.h, fsp_flags_is_valid(), @@ -364,6 +366,15 @@ struct fil_space_t { { return stop_new_ops; } + + /** Clamp a page number for batched I/O, such as read-ahead. + @param offset page number limit + @return offset clamped to the tablespace size */ + ulint max_page_number_for_io(ulint offset) const + { + const ulint limit= committed_size; + return limit > offset ? offset : limit; + } }; /** Value of fil_space_t::magic_n */ diff --git a/storage/xtradb/include/mtr0mtr.h b/storage/xtradb/include/mtr0mtr.h index 2d3da4d2a25..7d115eed5fd 100644 --- a/storage/xtradb/include/mtr0mtr.h +++ b/storage/xtradb/include/mtr0mtr.h @@ -2,6 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2013, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -57,6 +58,7 @@ first 3 values must be RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */ #endif /* UNIV_DEBUG */ #define MTR_MEMO_S_LOCK 55 #define MTR_MEMO_X_LOCK 56 +#define MTR_MEMO_SPACE_X_LOCK 57 /** @name Log item types The log items are declared 'byte' so that the compiler can warn if val @@ -293,6 +295,8 @@ This macro locks an rw-lock in s-mode. */ This macro locks an rw-lock in x-mode. */ #define mtr_x_lock(B, MTR) mtr_x_lock_func((B), __FILE__, __LINE__,\ (MTR)) +#define mtr_x_space_lock(B, MTR) mtr_x_space_lock_func(B, __FILE__, __LINE__,\ + MTR) /*********************************************************************//** NOTE! Use the macro above! Locks a lock in s-mode. */ @@ -315,6 +319,14 @@ mtr_x_lock_func( const char* file, /*!< in: file name */ ulint line, /*!< in: line number */ mtr_t* mtr); /*!< in: mtr */ + +/** Acquire exclusive tablespace latch. +@param lock fil_space_t::latch +@param file source code file name of the caller +@param line source code line number of the caller +@param mtr mini-transaction */ +inline void mtr_x_space_lock_func(prio_rw_lock_t *lock, + const char *file, ulint line, mtr_t *mtr); #endif /* !UNIV_HOTBACKUP */ /***************************************************//** diff --git a/storage/xtradb/include/mtr0mtr.ic b/storage/xtradb/include/mtr0mtr.ic index a44728463ae..0aea0994267 100644 --- a/storage/xtradb/include/mtr0mtr.ic +++ b/storage/xtradb/include/mtr0mtr.ic @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -78,7 +79,7 @@ mtr_memo_push( ut_ad(object); ut_ad(type >= MTR_MEMO_PAGE_S_FIX); - ut_ad(type <= MTR_MEMO_X_LOCK); + ut_ad(type <= MTR_MEMO_SPACE_X_LOCK); ut_ad(mtr); ut_ad(mtr->magic_n == MTR_MAGIC_N); ut_ad(mtr->state == MTR_ACTIVE); @@ -293,4 +294,16 @@ mtr_x_lock_func( mtr_memo_push(mtr, lock, MTR_MEMO_X_LOCK); } + +/** Acquire exclusive tablespace latch. +@param lock fil_space_t::latch +@param file source code file name of the caller +@param line source code line number of the caller +@param mtr mini-transaction */ +inline void mtr_x_space_lock_func(prio_rw_lock_t *lock, + const char *file, ulint line, mtr_t *mtr) +{ + rw_lock_x_lock_inline(lock, 0, file, line); + mtr_memo_push(mtr, lock, MTR_MEMO_SPACE_X_LOCK); +} #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/xtradb/mtr/mtr0mtr.cc b/storage/xtradb/mtr/mtr0mtr.cc index 77af6e9eb60..a04f9cc84a3 100644 --- a/storage/xtradb/mtr/mtr0mtr.cc +++ b/storage/xtradb/mtr/mtr0mtr.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -88,6 +89,16 @@ mtr_memo_slot_release_func( case MTR_MEMO_X_LOCK: rw_lock_x_unlock((prio_rw_lock_t*) object); break; + case MTR_MEMO_SPACE_X_LOCK: + { + fil_space_t* space = reinterpret_cast( + static_cast(object) + - reinterpret_cast( + &static_cast(0)->latch)); + space->committed_size = space->size; + rw_lock_x_unlock(&space->latch); + } + break; #ifdef UNIV_DEBUG default: ut_ad(slot->type == MTR_MEMO_MODIFY); diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc index 153599391dc..b61a8349b07 100644 --- a/storage/xtradb/srv/srv0start.cc +++ b/storage/xtradb/srv/srv0start.cc @@ -3,7 +3,7 @@ Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2019, MariaDB Corporation. +Copyright (c) 2013, 2020, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1240,6 +1240,10 @@ check_first_page: } } + if (fil_space_t* s = fil_space_get(0)) { + s->committed_size = s->size; + } + return(DB_SUCCESS); } @@ -1408,6 +1412,10 @@ srv_undo_tablespace_open( if (fil_node_create(name, (ulint) n_pages, space, FALSE)) { err = DB_SUCCESS; } + + if (fil_space_t* s = fil_space_get(space)) { + s->committed_size = n_pages; + } } return(err); diff --git a/storage/xtradb/trx/trx0rseg.cc b/storage/xtradb/trx/trx0rseg.cc index 1d0eb6d29fd..8ce6fb6729f 100644 --- a/storage/xtradb/trx/trx0rseg.cc +++ b/storage/xtradb/trx/trx0rseg.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -65,7 +65,7 @@ trx_rseg_header_create( ut_ad(mtr); ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL), - MTR_MEMO_X_LOCK)); + MTR_MEMO_SPACE_X_LOCK)); /* Allocate a new file segment for the rollback segment */ block = fseg_create(space, 0, TRX_RSEG + TRX_RSEG_FSEG_HEADER, mtr); @@ -312,7 +312,7 @@ trx_rseg_create(ulint space) /* To obey the latching order, acquire the file space x-latch before the trx_sys->mutex. */ - mtr_x_lock(fil_space_get_latch(space, NULL), &mtr); + mtr_x_space_lock(fil_space_get_latch(space, NULL), &mtr); slot_no = trx_sysf_rseg_find_free(&mtr); diff --git a/storage/xtradb/trx/trx0sys.cc b/storage/xtradb/trx/trx0sys.cc index fcdce291cf0..94a79a1f944 100644 --- a/storage/xtradb/trx/trx0sys.cc +++ b/storage/xtradb/trx/trx0sys.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -554,7 +554,7 @@ trx_sysf_create( then enter the kernel: we must do it in this order to conform to the latching order rules. */ - mtr_x_lock(fil_space_get_latch(TRX_SYS_SPACE, NULL), mtr); + mtr_x_space_lock(fil_space_get_latch(TRX_SYS_SPACE, NULL), mtr); /* Create the trx sys file block in a new allocated file segment */ block = fseg_create(TRX_SYS_SPACE, 0, TRX_SYS + TRX_SYS_FSEG_HEADER, -- cgit v1.2.1