diff --git a/client/mysqldump.c b/client/mysqldump.c index 7a76391f3fa..7d260ee18cb 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1251,8 +1251,9 @@ static int get_options(int *argc, char ***argv) if (opt_slave_data) { opt_lock_all_tables= !opt_single_transaction; - opt_master_data= 0; opt_delete_master_logs= 0; + if (opt_slave_data != MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL) + opt_master_data= 0; } /* Ensure consistency of the set of binlog & locking options */ @@ -1265,10 +1266,7 @@ static int get_options(int *argc, char ***argv) return(EX_USAGE); } if (opt_master_data) - { opt_lock_all_tables= !opt_single_transaction; - opt_slave_data= 0; - } if (opt_single_transaction || opt_lock_all_tables) lock_tables= 0; if (enclosed && opt_enclosed) @@ -6077,17 +6075,12 @@ static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos, } - /* SHOW MASTER STATUS reports file and position */ - print_comment(md_result_file, 0, - "\n--\n-- Position to start replication or point-in-time " - "recovery from\n--\n\n"); - fprintf(md_result_file, - "%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", - (use_gtid ? "-- " : comment_prefix), file, offset); + /* gtid */ if (have_mariadb_gtid) { print_comment(md_result_file, 0, - "\n--\n-- GTID to start replication from\n--\n\n"); + "\n-- Preferably use GTID to start replication from GTID " + "position:\n\n"); if (use_gtid) fprintf(md_result_file, "%sCHANGE MASTER TO MASTER_USE_GTID=slave_pos;\n", @@ -6096,6 +6089,19 @@ static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos, "%sSET GLOBAL gtid_slave_pos='%s';\n", (!use_gtid ? "-- " : comment_prefix), gtid_pos); } + + /* SHOW MASTER STATUS reports file and position */ + print_comment(md_result_file, 0, + "\n--\n-- Alternately, following is the position of the binary " + "logging from SHOW MASTER STATUS at point of backup." + "\n-- Use this when creating a replica of the primary server " + "where the backup was made." + "\n-- The new server will be connecting to the primary server " + "where the backup was taken." + "\n--\n\n"); + fprintf(md_result_file, + "%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", + (use_gtid ? "-- " : comment_prefix), file, offset); check_io(md_result_file); if (!consistent_binlog_pos) @@ -6174,7 +6180,6 @@ static int do_show_slave_status(MYSQL *mysql_con, int use_gtid, (opt_slave_data == MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL) ? "-- " : ""; const char *gtid_comment_prefix= (use_gtid ? comment_prefix : "-- "); const char *nogtid_comment_prefix= (!use_gtid ? comment_prefix : "-- "); - int set_gtid_done= 0; if (mysql_query_with_error_report(mysql_con, &slave, multi_source ? @@ -6190,23 +6195,36 @@ static int do_show_slave_status(MYSQL *mysql_con, int use_gtid, return 1; } + print_comment(md_result_file, 0, + "\n--\n-- The following is the SQL position of the replication " + "taken from SHOW SLAVE STATUS at the time of backup.\n" + "-- Use this position when creating a clone of, or replacement " + "server, from where the backup was taken." + "\n-- This new server will connects to the same primary " + "server%s.\n--\n", + multi_source ? "(s)" : ""); + + if (multi_source) + { + char gtid_pos[MAX_GTID_LENGTH]; + if (have_mariadb_gtid && get_gtid_pos(gtid_pos, 0)) + { + mysql_free_result(slave); + return 1; + } + print_comment(md_result_file, 0, + "-- GTID position to start replication:\n"); + fprintf(md_result_file, "%sSET GLOBAL gtid_slave_pos='%s';\n", + gtid_comment_prefix, gtid_pos); + } + if (use_gtid) + print_comment(md_result_file, 0, + "\n-- Use only the MASTER_USE_GTID=slave_pos or " + "MASTER_LOG_FILE/MASTER_LOG_POS in the statements below." + "\n\n"); + while ((row= mysql_fetch_row(slave))) { - if (multi_source && !set_gtid_done) - { - char gtid_pos[MAX_GTID_LENGTH]; - if (have_mariadb_gtid && get_gtid_pos(gtid_pos, 0)) - { - mysql_free_result(slave); - return 1; - } - if (opt_comments) - fprintf(md_result_file, "\n--\n-- Gtid position to start replication " - "from\n--\n\n"); - fprintf(md_result_file, "%sSET GLOBAL gtid_slave_pos='%s';\n", - gtid_comment_prefix, gtid_pos); - set_gtid_done= 1; - } if (row[9 + multi_source] && row[21 + multi_source]) { if (use_gtid) @@ -6220,11 +6238,6 @@ static int do_show_slave_status(MYSQL *mysql_con, int use_gtid, } /* SHOW MASTER STATUS reports file and position */ - if (opt_comments) - fprintf(md_result_file, - "\n--\n-- Position to start replication or point-in-time " - "recovery from (the master of this slave)\n--\n\n"); - if (multi_source) fprintf(md_result_file, "%sCHANGE MASTER '%.80s' TO ", nogtid_comment_prefix, row[0]); @@ -6245,6 +6258,7 @@ static int do_show_slave_status(MYSQL *mysql_con, int use_gtid, check_io(md_result_file); } } + fprintf(md_result_file, "\n"); mysql_free_result(slave); return 0; } diff --git a/include/mysql/service_print_check_msg.h b/include/mysql/service_print_check_msg.h new file mode 100644 index 00000000000..c2c7cf0a381 --- /dev/null +++ b/include/mysql/service_print_check_msg.h @@ -0,0 +1,44 @@ +/* Copyright (c) 2019, 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 Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#pragma once + +/** + @file include/mysql/service_print_check_msg.h + This service provides functions to write messages for check or repair +*/ + +#ifdef __cplusplus +extern "C" { +#endif + + +extern struct print_check_msg_service_st { + void (*print_check_msg)(MYSQL_THD, const char *db_name, const char *table_name, + const char *op, const char *msg_type, const char *message, + my_bool print_to_log); +} *print_check_msg_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN +# define print_check_msg_context(_THD) print_check_msg_service->print_check_msg +#else +extern void print_check_msg(MYSQL_THD, const char *db_name, const char *table_name, + const char *op, const char *msg_type, const char *message, + my_bool print_to_log); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/include/service_versions.h b/include/service_versions.h index ee250864287..cace4f37c69 100644 --- a/include/service_versions.h +++ b/include/service_versions.h @@ -45,3 +45,4 @@ #define VERSION_json 0x0100 #define VERSION_sql_service 0x0100 #define VERSION_thd_mdl 0x0100 +#define VERSION_print_check_msg 0x0100 diff --git a/libservices/CMakeLists.txt b/libservices/CMakeLists.txt index 6b47bb53fdb..d1329b665d5 100644 --- a/libservices/CMakeLists.txt +++ b/libservices/CMakeLists.txt @@ -25,6 +25,7 @@ SET(MYSQLSERVICES_SOURCES my_crypt_service.c my_md5_service.c my_print_error_service.c + print_check_msg_service.c my_sha1_service.c my_sha2_service.c my_snprintf_service.c diff --git a/libservices/print_check_msg_service.c b/libservices/print_check_msg_service.c new file mode 100644 index 00000000000..12f7bc51118 --- /dev/null +++ b/libservices/print_check_msg_service.c @@ -0,0 +1,18 @@ +/* Copyright (c) 2024, MariaDB Plc + + 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 Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +SERVICE_VERSION print_check_msg_context= (void*) VERSION_print_check_msg; diff --git a/mysql-test/main/rpl_mysqldump_slave.result b/mysql-test/main/rpl_mysqldump_slave.result index 9f93e3c405e..0d0378abd5b 100644 --- a/mysql-test/main/rpl_mysqldump_slave.result +++ b/mysql-test/main/rpl_mysqldump_slave.result @@ -9,23 +9,27 @@ use test; connection slave; -- SET GLOBAL gtid_slave_pos=''; CHANGE MASTER '' TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=BINLOG_START; + STOP ALL SLAVES; -- SET GLOBAL gtid_slave_pos=''; CHANGE MASTER '' TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=BINLOG_START; + START ALL SLAVES; STOP ALL SLAVES; -- SET GLOBAL gtid_slave_pos=''; CHANGE MASTER '' TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_MYPORT, MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=BINLOG_START; + START ALL SLAVES; start slave; Warnings: Note 1254 Slave is already running -- SET GLOBAL gtid_slave_pos=''; CHANGE MASTER '' TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=BINLOG_START; + start slave; Warnings: Note 1254 Slave is already running -*** Test mysqldump --dump-slave GTID functionality. +*** Test mysqldump --dump-slave GTID/non-gtid functionality. connection master; SET gtid_seq_no = 1000; CREATE TABLE t1 (a INT PRIMARY KEY); @@ -35,36 +39,170 @@ connection slave; CREATE TABLE t2 (a INT PRIMARY KEY); DROP TABLE t2; -1. --dump-slave=1 +1. --dump-slave=1 --gtid SET GLOBAL gtid_slave_pos='0-1-1001'; CHANGE MASTER '' TO MASTER_USE_GTID=slave_pos; -- CHANGE MASTER '' TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=BINLOG_START; -2. --dump-slave=2 + +1a. --dump-slave=1 + +-- SET GLOBAL gtid_slave_pos='0-1-1001'; +CHANGE MASTER '' TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=BINLOG_START; + + +2. --dump-slave=2 --gtid -- SET GLOBAL gtid_slave_pos='0-1-1001'; -- CHANGE MASTER '' TO MASTER_USE_GTID=slave_pos; -- CHANGE MASTER '' TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=BINLOG_START; -*** Test mysqldump --master-data GTID functionality. -1. --master-data=1 --- CHANGE MASTER TO MASTER_LOG_FILE='slave-bin.000001', MASTER_LOG_POS=BINLOG_START; +2. --dump-slave=2 + +-- SET GLOBAL gtid_slave_pos='0-1-1001'; +-- CHANGE MASTER '' TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=BINLOG_START; + +*** Test mysqldump --master-data GTID/non-gtid functionality. + +1. --master-data=1 --gtid + CHANGE MASTER TO MASTER_USE_GTID=slave_pos; SET GLOBAL gtid_slave_pos='0-2-1003'; - -2. --master-data=2 - -- CHANGE MASTER TO MASTER_LOG_FILE='slave-bin.000001', MASTER_LOG_POS=BINLOG_START; + +1a. --master-data=1 + +-- SET GLOBAL gtid_slave_pos='0-2-1003'; +CHANGE MASTER TO MASTER_LOG_FILE='slave-bin.000001', MASTER_LOG_POS=BINLOG_START; + +2. --master-data=2 --gtid + +-- CHANGE MASTER TO MASTER_USE_GTID=slave_pos; +-- SET GLOBAL gtid_slave_pos='0-2-1003'; +-- CHANGE MASTER TO MASTER_LOG_FILE='slave-bin.000001', MASTER_LOG_POS=BINLOG_START; + +2a. --master-data=2 + +-- SET GLOBAL gtid_slave_pos='0-2-1003'; +-- CHANGE MASTER TO MASTER_LOG_FILE='slave-bin.000001', MASTER_LOG_POS=BINLOG_START; + +3. --master-data --single-transaction --gtid + +CHANGE MASTER TO MASTER_USE_GTID=slave_pos; +SET GLOBAL gtid_slave_pos='0-2-1003'; +-- CHANGE MASTER TO MASTER_LOG_FILE='slave-bin.000001', MASTER_LOG_POS=BINLOG_START; + +3a. --master-data --single-transaction + +-- SET GLOBAL gtid_slave_pos='0-2-1003'; +CHANGE MASTER TO MASTER_LOG_FILE='slave-bin.000001', MASTER_LOG_POS=BINLOG_START; + +4. --master-data=2 --dump-slave=2 --single-transaction --gtid (MDEV-4827) + +-- MariaDB dump-- +-- Host: localhost Database: test +-- ------------------------------------------------------ +-- Server version +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- Preferably use GTID to start replication from GTID position: + -- CHANGE MASTER TO MASTER_USE_GTID=slave_pos; -- SET GLOBAL gtid_slave_pos='0-2-1003'; -3. --master-data --single-transaction +-- +-- Alternately, following is the position of the binary logging from SHOW MASTER STATUS at point of backup. +-- Use this when creating a replica of the primary server where the backup was made. +-- The new server will be connecting to the primary server where the backup was taken. +-- -- CHANGE MASTER TO MASTER_LOG_FILE='slave-bin.000001', MASTER_LOG_POS=BINLOG_START; -CHANGE MASTER TO MASTER_USE_GTID=slave_pos; -SET GLOBAL gtid_slave_pos='0-2-1003'; + +-- +-- The following is the SQL position of the replication taken from SHOW SLAVE STATUS at the time of backup. +-- Use this position when creating a clone of, or replacement server, from where the backup was taken. +-- This new server will connects to the same primary server(s). +-- +-- GTID position to start replication: +-- SET GLOBAL gtid_slave_pos='0-1-1001'; + +-- Use only the MASTER_USE_GTID=slave_pos or MASTER_LOG_FILE/MASTER_LOG_POS in the statements below. + +-- CHANGE MASTER '' TO MASTER_USE_GTID=slave_pos; +-- CHANGE MASTER '' TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=BINLOG_START; + +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed + +4a. --master-data=2 --dump-slave=2 --single-transaction (MDEV-4827) + +-- MariaDB dump-- +-- Host: localhost Database: test +-- ------------------------------------------------------ +-- Server version +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- Preferably use GTID to start replication from GTID position: + +-- SET GLOBAL gtid_slave_pos='0-2-1003'; + +-- +-- Alternately, following is the position of the binary logging from SHOW MASTER STATUS at point of backup. +-- Use this when creating a replica of the primary server where the backup was made. +-- The new server will be connecting to the primary server where the backup was taken. +-- + +-- CHANGE MASTER TO MASTER_LOG_FILE='slave-bin.000001', MASTER_LOG_POS=BINLOG_START; + +-- +-- The following is the SQL position of the replication taken from SHOW SLAVE STATUS at the time of backup. +-- Use this position when creating a clone of, or replacement server, from where the backup was taken. +-- This new server will connects to the same primary server(s). +-- +-- GTID position to start replication: +-- SET GLOBAL gtid_slave_pos='0-1-1001'; +-- CHANGE MASTER '' TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=BINLOG_START; + +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed connection master; CREATE TABLE t ( id int @@ -77,8 +215,8 @@ include/stop_slave.inc change master to master_use_gtid=slave_pos; connection master; # Ensuring the binlog dump thread is killed on primary... --- CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000002', MASTER_LOG_POS=BINLOG_START; -- SET GLOBAL gtid_slave_pos='0-1-1005'; +-- CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000002', MASTER_LOG_POS=BINLOG_START; connection slave; include/start_slave.inc include/rpl_end.inc diff --git a/mysql-test/main/rpl_mysqldump_slave.test b/mysql-test/main/rpl_mysqldump_slave.test index 0273e196db5..9dbee604520 100644 --- a/mysql-test/main/rpl_mysqldump_slave.test +++ b/mysql-test/main/rpl_mysqldump_slave.test @@ -37,7 +37,7 @@ start slave; start slave; ---echo *** Test mysqldump --dump-slave GTID functionality. +--echo *** Test mysqldump --dump-slave GTID/non-gtid functionality. --connection master SET gtid_seq_no = 1000; @@ -52,37 +52,80 @@ CREATE TABLE t2 (a INT PRIMARY KEY); DROP TABLE t2; --echo ---echo 1. --dump-slave=1 +--echo 1. --dump-slave=1 --gtid --echo --replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/ --exec $MYSQL_DUMP_SLAVE --compact --dump-slave=1 --gtid test --echo ---echo 2. --dump-slave=2 +--echo 1a. --dump-slave=1 +--echo +--replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/ +--exec $MYSQL_DUMP_SLAVE --compact --dump-slave=1 test + +--echo +--echo 2. --dump-slave=2 --gtid --echo --replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/ --exec $MYSQL_DUMP_SLAVE --compact --dump-slave=2 --gtid test - ---echo *** Test mysqldump --master-data GTID functionality. --echo ---echo 1. --master-data=1 +--echo 2. --dump-slave=2 +--echo +--replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/ +--exec $MYSQL_DUMP_SLAVE --compact --dump-slave=2 test + + +--echo *** Test mysqldump --master-data GTID/non-gtid functionality. +--echo +--echo 1. --master-data=1 --gtid --echo --replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/ --exec $MYSQL_DUMP_SLAVE --compact --master-data=1 --gtid test --echo ---echo 2. --master-data=2 +--echo 1a. --master-data=1 +--echo +--replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/ +--exec $MYSQL_DUMP_SLAVE --compact --master-data=1 test + +--echo +--echo 2. --master-data=2 --gtid --echo --replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/ --exec $MYSQL_DUMP_SLAVE --compact --master-data=2 --gtid test --echo ---echo 3. --master-data --single-transaction +--echo 2a. --master-data=2 +--echo +--replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/ +--exec $MYSQL_DUMP_SLAVE --compact --master-data=2 test + +--echo +--echo 3. --master-data --single-transaction --gtid --echo --replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/ --exec $MYSQL_DUMP_SLAVE --compact --master-data --single-transaction --gtid test +--echo +--echo 3a. --master-data --single-transaction +--echo +--replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/ +--exec $MYSQL_DUMP_SLAVE --compact --master-data --single-transaction test + +--echo +--echo 4. --master-data=2 --dump-slave=2 --single-transaction --gtid (MDEV-4827) +--echo +--replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/ /MariaDB dump.*/MariaDB dump/ /Dump completed.*/Dump completed/ /Server version.*/Server version/ +--exec $MYSQL_DUMP_SLAVE --master-data=2 --dump-slave=2 --single-transaction --gtid test +--echo + +--echo +--echo 4a. --master-data=2 --dump-slave=2 --single-transaction (MDEV-4827) +--echo +--replace_regex /MASTER_LOG_POS=[0-9]+/MASTER_LOG_POS=BINLOG_START/ /MariaDB dump.*/MariaDB dump/ /Dump completed.*/Dump completed/ /Server version.*/Server version/ +--exec $MYSQL_DUMP_SLAVE --master-data=2 --dump-slave=2 --single-transaction test +--echo # # MDEV-32611 Added test for mysqldump --delete-master-logs option. # This options is alias of diff --git a/mysql-test/std_data/autoinc_import_101.frm b/mysql-test/std_data/autoinc_import_101.frm new file mode 100644 index 00000000000..b16ae91b110 Binary files /dev/null and b/mysql-test/std_data/autoinc_import_101.frm differ diff --git a/mysql-test/std_data/autoinc_import_57.frm b/mysql-test/std_data/autoinc_import_57.frm new file mode 100644 index 00000000000..a333931b97b Binary files /dev/null and b/mysql-test/std_data/autoinc_import_57.frm differ diff --git a/mysql-test/suite/encryption/r/innodb-redo-nokeys.result b/mysql-test/suite/encryption/r/innodb-redo-nokeys.result index ce24c7c7033..5db7c6889ce 100644 --- a/mysql-test/suite/encryption/r/innodb-redo-nokeys.result +++ b/mysql-test/suite/encryption/r/innodb-redo-nokeys.result @@ -21,6 +21,15 @@ insert into t2 select * from t1; insert into t3 select * from t1; insert into t4 select * from t1; commit; + +# Flush all dirty pages from buffer pool +SET @no_checkpoint_save_pct= @@GLOBAL.innodb_max_dirty_pages_pct; +SET @no_checkpoint_save_pct_lwm= @@GLOBAL.innodb_max_dirty_pages_pct_lwm; +SET GLOBAL innodb_max_dirty_pages_pct_lwm=0.0; +SET GLOBAL innodb_max_dirty_pages_pct=0.0; +SET GLOBAL innodb_max_dirty_pages_pct= @no_checkpoint_save_pct; +SET GLOBAL innodb_max_dirty_pages_pct_lwm= @no_checkpoint_save_pct_lwm; + CREATE TABLE t5 (a VARCHAR(8)) ENGINE=InnoDB ENCRYPTED=YES; SET GLOBAL innodb_flush_log_at_trx_commit=1; begin; @@ -40,6 +49,6 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' AND support IN ('YES', 'DEFAULT', 'ENABLED'); ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS -FOUND 1 /\[ERROR\] InnoDB: Encryption key is not found for .*test.t1.ibd/ in mysqld.1.err +FOUND 1 /\[ERROR\] InnoDB: Encryption key is not found for .*test.t[1-5].ibd/ in mysqld.1.err # restart: --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys2.txt drop table t1,t2,t3,t4,t5; diff --git a/mysql-test/suite/encryption/t/innodb-redo-nokeys.test b/mysql-test/suite/encryption/t/innodb-redo-nokeys.test index 7323a9148c3..fe8208d05f0 100644 --- a/mysql-test/suite/encryption/t/innodb-redo-nokeys.test +++ b/mysql-test/suite/encryption/t/innodb-redo-nokeys.test @@ -42,7 +42,9 @@ insert into t3 select * from t1; insert into t4 select * from t1; commit; +let $no_checkpoint_flush= 1; --source ../../suite/innodb/include/no_checkpoint_start.inc + # # We test redo log page read at recv_read_page using # keys that are not in std_data/keys.txt. If checkpoint @@ -75,7 +77,7 @@ WHERE engine = 'innodb' AND support IN ('YES', 'DEFAULT', 'ENABLED'); let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err; -let SEARCH_PATTERN = \[ERROR\] InnoDB: Encryption key is not found for .*test.t1.ibd; +let SEARCH_PATTERN = \[ERROR\] InnoDB: Encryption key is not found for .*test.t[1-5].ibd; --source include/search_pattern_in_file.inc # diff --git a/mysql-test/suite/innodb/include/no_checkpoint_start.inc b/mysql-test/suite/innodb/include/no_checkpoint_start.inc index a903fee67d4..69823dd0a03 100644 --- a/mysql-test/suite/innodb/include/no_checkpoint_start.inc +++ b/mysql-test/suite/innodb/include/no_checkpoint_start.inc @@ -1,5 +1,28 @@ # Preparation for using no_checkpoint_end.inc +# no_checkpoint_flush: Set to trigger flushing the dirty pages from buffer pool +# and checkpoint before the "no checkpoint" block. + +if ($no_checkpoint_flush) { + --echo + --echo # Flush all dirty pages from buffer pool + SET @no_checkpoint_save_pct= @@GLOBAL.innodb_max_dirty_pages_pct; + SET @no_checkpoint_save_pct_lwm= @@GLOBAL.innodb_max_dirty_pages_pct_lwm; + + SET GLOBAL innodb_max_dirty_pages_pct_lwm=0.0; + SET GLOBAL innodb_max_dirty_pages_pct=0.0; + + let $wait_condition = + SELECT variable_value = 0 + FROM information_schema.global_status + WHERE variable_name = 'INNODB_BUFFER_POOL_PAGES_DIRTY'; + --source include/wait_condition.inc + + SET GLOBAL innodb_max_dirty_pages_pct= @no_checkpoint_save_pct; + SET GLOBAL innodb_max_dirty_pages_pct_lwm= @no_checkpoint_save_pct_lwm; + --echo +} + let MYSQLD_DATADIR= `select @@datadir`; --replace_regex /.*Last checkpoint at[ ]*([0-9]+).*/\1/ let CHECKPOINT_LSN=`SHOW ENGINE INNODB STATUS`; diff --git a/mysql-test/suite/innodb/r/autoinc_import.result b/mysql-test/suite/innodb/r/autoinc_import.result new file mode 100644 index 00000000000..4a8ddd02e3d --- /dev/null +++ b/mysql-test/suite/innodb/r/autoinc_import.result @@ -0,0 +1,232 @@ +CREATE TABLE t1 (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES(42); +CREATE TABLE t1b LIKE t1; +INSERT INTO t1b VALUES(3); +CREATE TABLE t1z LIKE t1; +CREATE TABLE t1t (id TINYINT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t0t LIKE t1t; +INSERT INTO t1t VALUES(123); +FLUSH TABLES t1,t1b,t1t FOR EXPORT; +UNLOCK TABLES; +CREATE TABLE t5_7 LIKE t1; +CREATE TABLE t5_7b LIKE t1b; +CREATE TABLE t10_1 LIKE t1; +CREATE TABLE t10_1b LIKE t1b; +ALTER TABLE t1 DISCARD TABLESPACE; +ALTER TABLE t1b DISCARD TABLESPACE; +ALTER TABLE t1z DISCARD TABLESPACE; +ALTER TABLE t1t DISCARD TABLESPACE; +ALTER TABLE t0t DISCARD TABLESPACE; +ALTER TABLE t5_7 DISCARD TABLESPACE; +ALTER TABLE t5_7b DISCARD TABLESPACE; +ALTER TABLE t10_1 DISCARD TABLESPACE; +ALTER TABLE t10_1b DISCARD TABLESPACE; +FLUSH TABLES; +ALTER TABLE t0t IMPORT TABLESPACE; +Warnings: +Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t0t.cfg', will attempt to import without schema verification +INSERT INTO t0t VALUES(NULL); +SELECT * FROM t0t; +id +123 +124 +DROP TABLE t0t; +ALTER TABLE t1 IMPORT TABLESPACE; +Warnings: +Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t1.cfg', will attempt to import without schema verification +ALTER TABLE t1b IMPORT TABLESPACE; +Warnings: +Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t1b.cfg', will attempt to import without schema verification +ALTER TABLE t1z IMPORT TABLESPACE; +Warnings: +Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t1z.cfg', will attempt to import without schema verification +ALTER TABLE t1t IMPORT TABLESPACE; +Warnings: +Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t1t.cfg', will attempt to import without schema verification +ALTER TABLE t5_7 IMPORT TABLESPACE; +Warnings: +Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t5_7.cfg', will attempt to import without schema verification +ALTER TABLE t5_7b IMPORT TABLESPACE; +Warnings: +Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t5_7b.cfg', will attempt to import without schema verification +ALTER TABLE t10_1 IMPORT TABLESPACE; +Warnings: +Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t10_1.cfg', will attempt to import without schema verification +ALTER TABLE t10_1b IMPORT TABLESPACE; +Warnings: +Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t10_1b.cfg', will attempt to import without schema verification +FOUND 1 /InnoDB: Resetting PAGE_ROOT_AUTO_INC from 128 to 123 on table `test`\.`t0t`/ in mysqld.1.err +FOUND 1 /InnoDB: Resetting PAGE_ROOT_AUTO_INC from 0 to 42 on table `test`\.`t1z`/ in mysqld.1.err +FOUND 1 /InnoDB: Resetting PAGE_ROOT_AUTO_INC from 128 to 123 on table `test`\.`t1t`/ in mysqld.1.err +FOUND 1 /InnoDB: Resetting PAGE_ROOT_AUTO_INC from 3 to 42 on table `test`\.`t5_7` \(created with version 50744\)/ in mysqld.1.err +FOUND 1 /InnoDB: Resetting PAGE_ROOT_AUTO_INC from 3 to 42 on table `test`\.`t10_1` \(created with version 100149\)/ in mysqld.1.err +FOUND 5 /InnoDB: Resetting PAGE_ROOT_AUTO_INC/ in mysqld.1.err +# restart: --read-only +CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b; +Table Op Msg_type Msg_text +test.t1 check status OK +test.t1b check status OK +test.t1t check status OK +test.t1z check status OK +test.t5_7 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed +test.t5_7 check status OK +test.t5_7b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed +test.t5_7b check status OK +test.t10_1 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed +test.t10_1 check status OK +test.t10_1b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed +test.t10_1b check status OK +CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE; +Table Op Msg_type Msg_text +test.t1 check status OK +test.t1b check status OK +test.t1t check status OK +test.t1z check status OK +test.t5_7 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed +test.t5_7 check status OK +test.t5_7b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed +test.t5_7b check status OK +test.t10_1 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed +test.t10_1 check status OK +test.t10_1b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed +test.t10_1b check status OK +# restart: --innodb-read-only --read-only +CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b; +Table Op Msg_type Msg_text +test.t1 check status OK +test.t1b check status OK +test.t1t check status OK +test.t1z check status OK +test.t5_7 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed +test.t5_7 check status OK +test.t5_7b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed +test.t5_7b check status OK +test.t10_1 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed +test.t10_1 check status OK +test.t10_1b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed +test.t10_1b check status OK +CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE; +Table Op Msg_type Msg_text +test.t1 check status OK +test.t1b check status OK +test.t1t check status OK +test.t1z check status OK +test.t5_7 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed +test.t5_7 check status OK +test.t5_7b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed +test.t5_7b check status OK +test.t10_1 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed +test.t10_1 check status OK +test.t10_1b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed +test.t10_1b check status OK +# restart: --innodb-read-only +CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b; +Table Op Msg_type Msg_text +test.t1 check status OK +test.t1b check status OK +test.t1t check status OK +test.t1z check status OK +test.t5_7 check status Operation failed +test.t5_7b check status Operation failed +test.t10_1 check status Operation failed +test.t10_1b check status Operation failed +CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE; +Table Op Msg_type Msg_text +test.t1 check status OK +test.t1b check status OK +test.t1t check status OK +test.t1z check status OK +test.t5_7 check status Operation failed +test.t5_7b check status Operation failed +test.t10_1 check status Operation failed +test.t10_1b check status Operation failed +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +SELECT COUNT(*) FROM t1b; +COUNT(*) +1 +SELECT COUNT(*) FROM t1t; +COUNT(*) +1 +SELECT COUNT(*) FROM t1z; +COUNT(*) +1 +SELECT COUNT(*) FROM t5_7; +COUNT(*) +1 +SELECT COUNT(*) FROM t5_7b; +COUNT(*) +1 +SELECT COUNT(*) FROM t10_1; +COUNT(*) +1 +SELECT COUNT(*) FROM t10_1b; +COUNT(*) +1 +# restart +CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE; +Table Op Msg_type Msg_text +test.t1 check status OK +test.t1b check status OK +test.t1t check status OK +test.t1z check status OK +test.t5_7 check note Auto_increment checked and .frm file version updated +test.t5_7 check status OK +test.t5_7b check note Auto_increment checked and .frm file version updated +test.t5_7b check status OK +test.t10_1 check note Auto_increment checked and .frm file version updated +test.t10_1 check status OK +test.t10_1b check note Auto_increment checked and .frm file version updated +test.t10_1b check status OK +INSERT INTO t1 VALUES(NULL); +INSERT INTO t1b VALUES(NULL); +INSERT INTO t1t VALUES(NULL); +INSERT INTO t1z VALUES(NULL); +INSERT INTO t5_7 VALUES(NULL); +INSERT INTO t5_7b VALUES(NULL); +INSERT INTO t10_1 VALUES(NULL); +INSERT INTO t10_1b VALUES(NULL); +CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE; +Table Op Msg_type Msg_text +test.t1 check status OK +test.t1b check status OK +test.t1t check status OK +test.t1z check status OK +test.t5_7 check status OK +test.t5_7b check status OK +test.t10_1 check status OK +test.t10_1b check status OK +SELECT * FROM t1; +id +4 +42 +SELECT * FROM t1b; +id +3 +347 +SELECT * FROM t1t; +id +123 +124 +SELECT * FROM t1z; +id +42 +43 +SELECT * FROM t5_7; +id +42 +43 +SELECT * FROM t5_7b; +id +3 +347 +SELECT * FROM t10_1; +id +42 +43 +SELECT * FROM t10_1b; +id +3 +347 +DROP TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b; diff --git a/mysql-test/suite/innodb/t/autoinc_import.test b/mysql-test/suite/innodb/t/autoinc_import.test new file mode 100644 index 00000000000..e137413dfb5 --- /dev/null +++ b/mysql-test/suite/innodb/t/autoinc_import.test @@ -0,0 +1,168 @@ +--source include/have_innodb.inc + +CREATE TABLE t1 (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES(42); +CREATE TABLE t1b LIKE t1; +INSERT INTO t1b VALUES(3); +CREATE TABLE t1z LIKE t1; +CREATE TABLE t1t (id TINYINT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t0t LIKE t1t; +INSERT INTO t1t VALUES(123); +--let DATADIR=`select @@datadir` +--let PAGE_SIZE=`select @@innodb_page_size` +FLUSH TABLES t1,t1b,t1t FOR EXPORT; +--copy_file $DATADIR/test/t1.ibd $DATADIR/test/t.ibd +--copy_file $DATADIR/test/t1.ibd $DATADIR/test/tz.ibd +--copy_file $DATADIR/test/t1b.ibd $DATADIR/test/tb.ibd +--copy_file $DATADIR/test/t1t.ibd $DATADIR/test/tt.ibd +UNLOCK TABLES; +CREATE TABLE t5_7 LIKE t1; +CREATE TABLE t5_7b LIKE t1b; +CREATE TABLE t10_1 LIKE t1; +CREATE TABLE t10_1b LIKE t1b; +ALTER TABLE t1 DISCARD TABLESPACE; +ALTER TABLE t1b DISCARD TABLESPACE; +ALTER TABLE t1z DISCARD TABLESPACE; +ALTER TABLE t1t DISCARD TABLESPACE; +ALTER TABLE t0t DISCARD TABLESPACE; +ALTER TABLE t5_7 DISCARD TABLESPACE; +ALTER TABLE t5_7b DISCARD TABLESPACE; +ALTER TABLE t10_1 DISCARD TABLESPACE; +ALTER TABLE t10_1b DISCARD TABLESPACE; +FLUSH TABLES; + +# Update the PAGE_ROOT_AUTO_INC field of a few files. +perl; +do "$ENV{MTR_SUITE_DIR}/include/crc32.pl"; +sub update_autoinc +{ + my ($file, $value) = @_; + open(FILE, "+<$file") || die "Unable to open $file"; + binmode FILE; + my $ps= $ENV{PAGE_SIZE}; + my $page; + die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps; + my $full_crc32 = unpack("N",substr($page,54,4)) & 0x10; # FIL_SPACE_FLAGS + sysseek(FILE, 3*$ps, 0) || die "Unable to seek $file\n"; + die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps; + substr($page,56,8)=pack("NN",0,$value); + my $polynomial = 0x82f63b78; # CRC-32C + if ($full_crc32) { + my $ck = mycrc32(substr($page, 0, $ps-4), 0, $polynomial); + substr($page, $ps-4, 4) = pack("N", $ck); + } + else + { + my $ck= pack("N",mycrc32(substr($page, 4, 22), 0, $polynomial) ^ + mycrc32(substr($page, 38, $ps - 38 - 8), 0, $polynomial)); + substr($page,0,4)=$ck; + substr($page,$ps-8,4)=$ck; + } + sysseek(FILE, 3*$ps, 0) || die "Unable to rewind $file\n"; + syswrite(FILE, $page, $ps)==$ps || die "Unable to write $file\n"; + close(FILE) || die "Unable to close $file"; +} +update_autoinc("$ENV{DATADIR}/test/tz.ibd", 0); +update_autoinc("$ENV{DATADIR}/test/t.ibd", 3); +update_autoinc("$ENV{DATADIR}/test/tb.ibd", 346); +update_autoinc("$ENV{DATADIR}/test/tt.ibd", 128); +EOF + +--remove_file $DATADIR/test/t5_7.frm +--remove_file $DATADIR/test/t5_7b.frm +--copy_file $MYSQL_TEST_DIR/std_data/autoinc_import_57.frm $DATADIR/test/t5_7.frm +--copy_file $MYSQL_TEST_DIR/std_data/autoinc_import_57.frm $DATADIR/test/t5_7b.frm +--remove_file $DATADIR/test/t10_1.frm +--remove_file $DATADIR/test/t10_1b.frm +--copy_file $MYSQL_TEST_DIR/std_data/autoinc_import_101.frm $DATADIR/test/t10_1.frm +--copy_file $MYSQL_TEST_DIR/std_data/autoinc_import_101.frm $DATADIR/test/t10_1b.frm +--copy_file $DATADIR/test/t.ibd $DATADIR/test/t5_7.ibd +--copy_file $DATADIR/test/tb.ibd $DATADIR/test/t5_7b.ibd +--copy_file $DATADIR/test/t.ibd $DATADIR/test/t10_1.ibd +--copy_file $DATADIR/test/tb.ibd $DATADIR/test/t10_1b.ibd +--move_file $DATADIR/test/t.ibd $DATADIR/test/t1.ibd +--move_file $DATADIR/test/tb.ibd $DATADIR/test/t1b.ibd +--copy_file $DATADIR/test/tt.ibd $DATADIR/test/t0t.ibd +--move_file $DATADIR/test/tt.ibd $DATADIR/test/t1t.ibd +--move_file $DATADIR/test/tz.ibd $DATADIR/test/t1z.ibd + +ALTER TABLE t0t IMPORT TABLESPACE; +INSERT INTO t0t VALUES(NULL); +SELECT * FROM t0t; +DROP TABLE t0t; +ALTER TABLE t1 IMPORT TABLESPACE; +ALTER TABLE t1b IMPORT TABLESPACE; +ALTER TABLE t1z IMPORT TABLESPACE; +ALTER TABLE t1t IMPORT TABLESPACE; +ALTER TABLE t5_7 IMPORT TABLESPACE; +ALTER TABLE t5_7b IMPORT TABLESPACE; +ALTER TABLE t10_1 IMPORT TABLESPACE; +ALTER TABLE t10_1b IMPORT TABLESPACE; + +--let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let SEARCH_PATTERN= InnoDB: Resetting PAGE_ROOT_AUTO_INC from 128 to 123 on table `test`\.`t0t` +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN= InnoDB: Resetting PAGE_ROOT_AUTO_INC from 0 to 42 on table `test`\.`t1z` +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN= InnoDB: Resetting PAGE_ROOT_AUTO_INC from 128 to 123 on table `test`\.`t1t` +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN= InnoDB: Resetting PAGE_ROOT_AUTO_INC from 3 to 42 on table `test`\.`t5_7` \(created with version 50744\) +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN= InnoDB: Resetting PAGE_ROOT_AUTO_INC from 3 to 42 on table `test`\.`t10_1` \(created with version 100149\) +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN= InnoDB: Resetting PAGE_ROOT_AUTO_INC +--source include/search_pattern_in_file.inc + +# Restart, so that the InnoDB tables will be loaded into the data dictionary. +--let $restart_parameters=--read-only +--source include/restart_mysqld.inc + +CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b; +CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE; + +--let $restart_parameters=--innodb-read-only --read-only +--source include/restart_mysqld.inc + +CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b; +CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE; + +--let $restart_parameters=--innodb-read-only +--source include/restart_mysqld.inc + +CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b; +CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE; + +SELECT COUNT(*) FROM t1; +SELECT COUNT(*) FROM t1b; +SELECT COUNT(*) FROM t1t; +SELECT COUNT(*) FROM t1z; +SELECT COUNT(*) FROM t5_7; +SELECT COUNT(*) FROM t5_7b; +SELECT COUNT(*) FROM t10_1; +SELECT COUNT(*) FROM t10_1b; + +--let $restart_parameters= +--source include/restart_mysqld.inc + +CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE; + +INSERT INTO t1 VALUES(NULL); +INSERT INTO t1b VALUES(NULL); +INSERT INTO t1t VALUES(NULL); +INSERT INTO t1z VALUES(NULL); +INSERT INTO t5_7 VALUES(NULL); +INSERT INTO t5_7b VALUES(NULL); +INSERT INTO t10_1 VALUES(NULL); +INSERT INTO t10_1b VALUES(NULL); + +CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE; + +SELECT * FROM t1; +SELECT * FROM t1b; +SELECT * FROM t1t; +SELECT * FROM t1z; +SELECT * FROM t5_7; +SELECT * FROM t5_7b; +SELECT * FROM t10_1; +SELECT * FROM t10_1b; +DROP TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b; diff --git a/mysql-test/suite/mariabackup/partial.result b/mysql-test/suite/mariabackup/partial.result index 981bef4e40c..9ff3a20c01f 100644 --- a/mysql-test/suite/mariabackup/partial.result +++ b/mysql-test/suite/mariabackup/partial.result @@ -14,6 +14,14 @@ ALTER TABLE t1 IMPORT TABLESPACE; SELECT * FROM t1; i 1 +# MDEV-33023 Crash in mariadb-backup --prepare --export after --prepare +t1.cfg +t21.cfg +ALTER TABLE t1 DISCARD TABLESPACE; +ALTER TABLE t1 IMPORT TABLESPACE; +SELECT * FROM t1; +i +1 DROP TABLE t1; DROP TABLE t2; DROP TABLE t21; diff --git a/mysql-test/suite/mariabackup/partial.test b/mysql-test/suite/mariabackup/partial.test index d0d07daf2ea..85808749b62 100644 --- a/mysql-test/suite/mariabackup/partial.test +++ b/mysql-test/suite/mariabackup/partial.test @@ -55,6 +55,25 @@ copy_file $targetdir/test/t1.cfg $MYSQLD_DATADIR/test/t1.cfg; ALTER TABLE t1 IMPORT TABLESPACE; SELECT * FROM t1; + +--echo # MDEV-33023 Crash in mariadb-backup --prepare --export after --prepare +--disable_result_log +exec $XTRABACKUP --defaults-file=$server_cnf --defaults-group-suffix=.1 --prepare --target-dir=$targetdir; +exec $XTRABACKUP --defaults-file=$server_cnf --defaults-group-suffix=.1 --prepare --export --target-dir=$targetdir; +--enable_result_log + +list_files $targetdir/test *.cfg; +# There must not be binary logs created on --prepare step +list_files $targetdir/ mysqld-bin.*; + +let $MYSQLD_DATADIR= `select @@datadir`; +ALTER TABLE t1 DISCARD TABLESPACE; +copy_file $targetdir/test/t1.ibd $MYSQLD_DATADIR/test/t1.ibd; +copy_file $targetdir/test/t1.cfg $MYSQLD_DATADIR/test/t1.cfg; +ALTER TABLE t1 IMPORT TABLESPACE; + +SELECT * FROM t1; + DROP TABLE t1; DROP TABLE t2; DROP TABLE t21; diff --git a/plugin/cracklib_password_check/CMakeLists.txt b/plugin/cracklib_password_check/CMakeLists.txt index 79b3b80fbef..263495838aa 100644 --- a/plugin/cracklib_password_check/CMakeLists.txt +++ b/plugin/cracklib_password_check/CMakeLists.txt @@ -32,11 +32,12 @@ IF (HAVE_ALLOCA_H AND HAVE_CRACK_H AND HAVE_LIBCRACK AND HAVE_MEMCPY) IF(CHECKMODULE AND SEMODULE_PACKAGE) FOREACH(pol mariadb-plugin-cracklib-password-check) SET(src ${CMAKE_CURRENT_SOURCE_DIR}/policy/selinux/${pol}.te) - SET(tmp ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${pol}-pp.dir/${pol}.mod) + SET(tmp ${CMAKE_CURRENT_BINARY_DIR}/${pol}.mod) SET(out ${CMAKE_CURRENT_BINARY_DIR}/${pol}.pp) ADD_CUSTOM_COMMAND(OUTPUT ${out} COMMAND ${CHECKMODULE} -M -m ${src} -o ${tmp} COMMAND ${SEMODULE_PACKAGE} -m ${tmp} -o ${out} + COMMAND ${CMAKE_COMMAND} -E remove ${tmp} DEPENDS ${src}) ADD_CUSTOM_TARGET(${pol}-pp ALL DEPENDS ${out}) INSTALL(FILES ${out} DESTINATION ${inst_location}/policy/selinux COMPONENT cracklib-password-check) diff --git a/sql/handler.cc b/sql/handler.cc index 86fc697ec0c..ac40f9dbcff 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -5022,7 +5022,7 @@ int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt) if (unlikely((error= check(thd, check_opt)))) return error; /* Skip updating frm version if not main handler. */ - if (table->file != this) + if (table->file != this || opt_readonly) return error; return update_frm_version(table); } @@ -5071,7 +5071,7 @@ int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt) DBUG_ASSERT(result == HA_ADMIN_NOT_IMPLEMENTED || ha_table_flags() & HA_CAN_REPAIR); - if (result == HA_ADMIN_OK) + if (result == HA_ADMIN_OK && !opt_readonly) result= update_frm_version(table); return result; } @@ -6004,7 +6004,7 @@ err: void st_ha_check_opt::init() { - flags= sql_flags= 0; + flags= sql_flags= handler_flags= 0; start_time= my_time(0); } diff --git a/sql/handler.h b/sql/handler.h index 2d01979ab48..58e8bf64662 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -2768,6 +2768,7 @@ typedef struct st_ha_check_opt st_ha_check_opt() = default; /* Remove gcc warning */ uint flags; /* isam layer flags (e.g. for myisamchk) */ uint sql_flags; /* sql layer flags - for something myisamchk cannot do */ + uint handler_flags; /* Reserved for handler usage */ time_t start_time; /* When check/repair starts */ KEY_CACHE *key_cache; /* new key cache when changing key cache */ void init(); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index da98be9bf2f..0433156ef40 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -5713,6 +5713,40 @@ extern "C" void *thd_mdl_context(MYSQL_THD thd) return &thd->mdl_context; } +/** + Send check/repair message to the user + + @param op one of check or repair + @param msg_type one of info, warning or error + @param print_to_log <> 0 if we should also print the message to error log. +*/ + +extern "C" void +print_check_msg(THD *thd, const char *db_name, const char *table_name, const char *op, + const char *msg_type, const char *message, my_bool print_to_log) +{ + char name[NAME_LEN * 2 + 2]; + Protocol *protocol= thd->protocol; + + DBUG_ASSERT(strlen(db_name) <= NAME_LEN); + DBUG_ASSERT(strlen(table_name) <= NAME_LEN); + + size_t length= size_t(strxnmov(name, sizeof name - 1, + db_name, ".", table_name, NullS) - + name); + protocol->prepare_for_resend(); + protocol->store(name, length, system_charset_info); + protocol->store(op, strlen(op), system_charset_info); + protocol->store(msg_type, strlen(msg_type), system_charset_info); + protocol->store(message, strlen(message), system_charset_info); + if (protocol->write()) + sql_print_error("Failed on my_net_write, writing to stderr instead: %s: %s\n", + table_name, message); + else if (thd->variables.log_warnings > 2 && print_to_log) + sql_print_error("%s: table '%s' got '%s' during %s", + msg_type, table_name, message, op); +} + /**************************************************************************** Handling of statement states in functions and triggers. diff --git a/sql/sql_plugin_services.inl b/sql/sql_plugin_services.inl index 426f295c7a9..263d840bc29 100644 --- a/sql/sql_plugin_services.inl +++ b/sql/sql_plugin_services.inl @@ -18,6 +18,7 @@ #include #include #include +#include struct st_service_ref { const char *name; @@ -219,6 +220,11 @@ static struct my_print_error_service_st my_print_error_handler= my_printv_error }; +static struct print_check_msg_service_st print_check_msg_handler= +{ + print_check_msg +}; + struct json_service_st json_handler= { json_type, @@ -266,6 +272,7 @@ static struct st_service_ref list_of_services[]= { "my_crypt_service", VERSION_my_crypt, &crypt_handler}, { "my_md5_service", VERSION_my_md5, &my_md5_handler}, { "my_print_error_service", VERSION_my_print_error, &my_print_error_handler}, + { "print_check_msg_service", VERSION_print_check_msg, &print_check_msg_handler}, { "my_sha1_service", VERSION_my_sha1, &my_sha1_handler}, { "my_sha2_service", VERSION_my_sha2, &my_sha2_handler}, { "my_snprintf_service", VERSION_my_snprintf, &my_snprintf_handler }, diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 5e106fbc2cd..36abb31303e 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -1291,54 +1291,71 @@ btr_read_autoinc(dict_index_t* index) return autoinc; } +dict_index_t *dict_table_t::get_index(const dict_col_t &col) const +{ + dict_index_t *index= dict_table_get_first_index(this); + + while (index && (index->fields[0].col != &col || index->is_corrupted())) + index= dict_table_get_next_index(index); + + return index; +} + /** Read the last used AUTO_INCREMENT value from PAGE_ROOT_AUTO_INC, or fall back to MAX(auto_increment_column). -@param[in] table table containing an AUTO_INCREMENT column -@param[in] col_no index of the AUTO_INCREMENT column -@return the AUTO_INCREMENT value -@retval 0 on error or if no AUTO_INCREMENT value was used yet */ -ib_uint64_t -btr_read_autoinc_with_fallback(const dict_table_t* table, unsigned col_no) +@param table table containing an AUTO_INCREMENT column +@param col_no index of the AUTO_INCREMENT column +@param mysql_version TABLE_SHARE::mysql_version +@param max the maximum value of the AUTO_INCREMENT column +@return the AUTO_INCREMENT value +@retval 0 on error or if no AUTO_INCREMENT value was used yet */ +uint64_t btr_read_autoinc_with_fallback(const dict_table_t *table, + unsigned col_no, ulong mysql_version, + uint64_t max) { - ut_ad(table->persistent_autoinc); - ut_ad(!table->is_temporary()); + ut_ad(table->persistent_autoinc); + ut_ad(!table->is_temporary()); - dict_index_t* index = dict_table_get_first_index(table); + uint64_t autoinc= 0; + mtr_t mtr; + mtr.start(); - if (index == NULL) { - return 0; - } + if (buf_block_t *block= + buf_page_get(page_id_t(table->space_id, + dict_table_get_first_index(table)->page), + table->space->zip_size(), RW_SX_LATCH, &mtr)) + { + autoinc= page_get_autoinc(block->page.frame); - mtr_t mtr; - mtr.start(); - buf_block_t* block = buf_page_get( - page_id_t(index->table->space_id, index->page), - index->table->space->zip_size(), - RW_S_LATCH, &mtr); + if (autoinc > 0 && autoinc <= max && mysql_version >= 100210); + else if (dict_index_t *index= + table->get_index(*dict_table_get_nth_col(table, col_no))) + { + /* Read MAX(autoinc_col), in case this table had originally been + created before MariaDB 10.2.4 introduced persistent AUTO_INCREMENT + and MariaDB 10.2.10 fixed MDEV-12123, and there could be a garbage + value in the PAGE_ROOT_AUTO_INC field. */ + const uint64_t max_autoinc= row_search_max_autoinc(index); + const bool need_adjust{autoinc > max || autoinc < max_autoinc}; + ut_ad(max_autoinc <= max); - ib_uint64_t autoinc = block - ? page_get_autoinc(block->page.frame) : 0; - const bool retry = block && autoinc == 0 - && !page_is_empty(block->page.frame); - mtr.commit(); + if (UNIV_UNLIKELY(need_adjust) && !high_level_read_only && !opt_readonly) + { + sql_print_information("InnoDB: Resetting PAGE_ROOT_AUTO_INC from " + UINT64PF " to " UINT64PF + " on table %`.*s.%`s (created with version %lu)", + autoinc, max_autoinc, + int(table->name.dblen()), table->name.m_name, + table->name.basename(), mysql_version); + autoinc= max_autoinc; + index->set_modified(mtr); + page_set_autoinc(block, max_autoinc, &mtr, true); + } + } + } - if (retry) { - /* This should be an old data file where - PAGE_ROOT_AUTO_INC was initialized to 0. - Fall back to reading MAX(autoinc_col). - There should be an index on it. */ - const dict_col_t* autoinc_col - = dict_table_get_nth_col(table, col_no); - while (index && index->fields[0].col != autoinc_col) { - index = dict_table_get_next_index(index); - } - - if (index) { - autoinc = row_search_max_autoinc(index); - } - } - - return autoinc; + mtr.commit(); + return autoinc; } /** Write the next available AUTO_INCREMENT value to PAGE_ROOT_AUTO_INC. diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 1cf6fa80ace..20eccff0df8 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -47,10 +47,13 @@ this program; if not, write to the Free Software Foundation, Inc., #include #include #include +#include #include "sql_type_geom.h" #include "scope.h" #include "srv0srv.h" +extern my_bool opt_readonly; + // MYSQL_PLUGIN_IMPORT extern my_bool lower_case_file_system; // MYSQL_PLUGIN_IMPORT extern char mysql_unpacked_real_data_home[]; @@ -111,6 +114,7 @@ thread_local ha_handler_stats mariadb_dummy_stats; thread_local ha_handler_stats *mariadb_stats= &mariadb_dummy_stats; #include +#include // TT_FOR_UPGRADE #define thd_get_trx_isolation(X) ((enum_tx_isolation)thd_tx_isolation(X)) @@ -5765,9 +5769,9 @@ func_exit: return ret; } -/********************************************************************//** -Get the upper limit of the MySQL integral and floating-point type. -@return maximum allowed value for the field */ +/** Get the maximum integer value of a numeric column. +@param field column definition +@return maximum allowed integer value */ ulonglong innobase_get_int_col_max_value(const Field *field) { ulonglong max_value = 0; @@ -5832,46 +5836,45 @@ ha_innobase::open(). @param[in,out] table persistent table @param[in] field the AUTO_INCREMENT column */ -static -void -initialize_auto_increment(dict_table_t* table, const Field* field) +static void initialize_auto_increment(dict_table_t *table, const Field& field, + const TABLE_SHARE &s) { - ut_ad(!table->is_temporary()); + ut_ad(!table->is_temporary()); + const unsigned col_no= innodb_col_no(&field); + table->autoinc_mutex.wr_lock(); + table->persistent_autoinc= + uint16_t(dict_table_get_nth_col_pos(table, col_no, nullptr) + 1) & + dict_index_t::MAX_N_FIELDS; + if (table->autoinc) + /* Already initialized. Our caller checked + table->persistent_autoinc without + autoinc_mutex protection, and there might be multiple + ha_innobase::open() executing concurrently. */; + else if (srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN) + /* If innodb_force_recovery is set so high that writes + are disabled we force the AUTOINC counter to 0 + value effectively disabling writes to the table. + Secondly, we avoid reading the table in case the read + results in failure due to a corrupted table/index. - const unsigned col_no = innodb_col_no(field); + We will not return an error to the client, so that the + tables can be dumped with minimal hassle. If an error + were returned in this case, the first attempt to read + the table would fail and subsequent SELECTs would succeed. */; + else if (table->persistent_autoinc) + { + uint64_t max_value= innobase_get_int_col_max_value(&field); + table->autoinc= + innobase_next_autoinc(btr_read_autoinc_with_fallback(table, col_no, + s.mysql_version, + max_value), + 1 /* need */, + 1 /* auto_increment_increment */, + 0 /* auto_increment_offset */, + max_value); + } - table->autoinc_mutex.wr_lock(); - - table->persistent_autoinc = static_cast( - dict_table_get_nth_col_pos(table, col_no, NULL) + 1) - & dict_index_t::MAX_N_FIELDS; - - if (table->autoinc) { - /* Already initialized. Our caller checked - table->persistent_autoinc without - autoinc_mutex protection, and there might be multiple - ha_innobase::open() executing concurrently. */ - } else if (srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN) { - /* If the recovery level is set so high that writes - are disabled we force the AUTOINC counter to 0 - value effectively disabling writes to the table. - Secondly, we avoid reading the table in case the read - results in failure due to a corrupted table/index. - - We will not return an error to the client, so that the - tables can be dumped with minimal hassle. If an error - were returned in this case, the first attempt to read - the table would fail and subsequent SELECTs would succeed. */ - } else if (table->persistent_autoinc) { - table->autoinc = innobase_next_autoinc( - btr_read_autoinc_with_fallback(table, col_no), - 1 /* need */, - 1 /* auto_increment_increment */, - 0 /* auto_increment_offset */, - innobase_get_int_col_max_value(field)); - } - - table->autoinc_mutex.wr_unlock(); + table->autoinc_mutex.wr_unlock(); } /** Open an InnoDB table @@ -6107,7 +6110,7 @@ ha_innobase::open(const char* name, int, uint) || m_prebuilt->table->persistent_autoinc || !m_prebuilt->table->is_readable()) { } else if (const Field* ai = table->found_next_number_field) { - initialize_auto_increment(m_prebuilt->table, ai); + initialize_auto_increment(m_prebuilt->table, *ai, *table->s); } /* Set plugin parser for fulltext index */ @@ -15171,6 +15174,7 @@ ha_innobase::check( ulint n_rows_in_table = ULINT_UNDEFINED; bool is_ok = true; dberr_t ret; + uint handler_flags= check_opt->handler_flags; DBUG_ENTER("ha_innobase::check"); DBUG_ASSERT(thd == ha_thd()); @@ -15179,6 +15183,27 @@ ha_innobase::check( ut_a(m_prebuilt->trx == thd_to_trx(thd)); ut_ad(m_prebuilt->trx->mysql_thd == thd); + if (handler_flags || check_for_upgrade(check_opt)) { + /* The file was already checked and fixed as part of open */ + print_check_msg(thd, table->s->db.str, table->s->table_name.str, + "check", "note", + (opt_readonly || high_level_read_only + || !(check_opt->sql_flags & TT_FOR_UPGRADE)) + ? "Auto_increment will be" + " checked on each open until" + " CHECK TABLE FOR UPGRADE is executed" + : "Auto_increment checked and" + " .frm file version updated", 1); + if (handler_flags && (check_opt->sql_flags & TT_FOR_UPGRADE)) { + /* + No other issues found (as handler_flags was only + set if there as not other problems with the table + than auto_increment). + */ + DBUG_RETURN(HA_ADMIN_OK); + } + } + if (m_prebuilt->mysql_template == NULL) { /* Build the template; we will use a dummy template in index scans done in checking */ @@ -15371,6 +15396,35 @@ ha_innobase::check( DBUG_RETURN(is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT); } +/** +Check if we there is a problem with the InnoDB table. +@param check_opt check options +@retval HA_ADMIN_OK if Table is ok +@retval HA_ADMIN_NEEDS_ALTER User should run ALTER TABLE FOR UPGRADE +@retval HA_ADMIN_NEEDS_CHECK User should run CHECK TABLE FOR UPGRADE +@retval HA_ADMIN_FAILED if InnoDB is in read-only mode */ +int ha_innobase::check_for_upgrade(HA_CHECK_OPT *check_opt) +{ + /* + Check if there is a possibility that the auto increment value + stored in PAGE_ROOT_AUTO_INC could be corrupt. + */ + if (table->s->mysql_version >= 100210); + else if (const Field *auto_increment= table->found_next_number_field) + { + uint col_no= innodb_col_no(auto_increment); + const dict_col_t *autoinc_col= + dict_table_get_nth_col(m_prebuilt->table, col_no); + if (m_prebuilt->table->get_index(*autoinc_col)) + { + check_opt->handler_flags= 1; + return (high_level_read_only && !opt_readonly) + ? HA_ADMIN_FAILED : HA_ADMIN_NEEDS_CHECK; + } + } + return HA_ADMIN_OK; +} + /*******************************************************************//** Gets the foreign key create info for a table stored in InnoDB. @return own: character string in the form which can be inserted to the diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 1f42bf180a8..50ac423f3a5 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -209,6 +209,7 @@ public: int rename_table(const char* from, const char* to) override; inline int defragment_table(); int check(THD* thd, HA_CHECK_OPT* check_opt) override; + int check_for_upgrade(HA_CHECK_OPT* check_opt) override; inline void reload_statistics(); @@ -909,6 +910,12 @@ unsigned innodb_col_no(const Field* field) MY_ATTRIBUTE((nonnull, warn_unused_result)); +/** Get the maximum integer value of a numeric column. +@param field column definition +@return maximum allowed integer value */ +ulonglong innobase_get_int_col_max_value(const Field *field) + MY_ATTRIBUTE((nonnull, warn_unused_result)); + /********************************************************************//** Helper function to push frm mismatch error to error log and if needed to sql-layer. */ diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index dc5c1f71925..72fda6b8ee7 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -1458,11 +1458,6 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx } }; -/********************************************************************//** -Get the upper limit of the MySQL integral and floating-point type. -@return maximum allowed value for the field */ -ulonglong innobase_get_int_col_max_value(const Field *field); - /** Determine if fulltext indexes exist in a given table. @param table MySQL table @return number of fulltext indexes */ @@ -9844,13 +9839,7 @@ commit_set_autoinc( const dict_col_t* autoinc_col = dict_table_get_nth_col(ctx->old_table, innodb_col_no(ai)); - dict_index_t* index - = dict_table_get_first_index(ctx->old_table); - while (index != NULL - && index->fields[0].col != autoinc_col) { - index = dict_table_get_next_index(index); - } - + auto index = ctx->old_table->get_index(*autoinc_col); ut_ad(index); ib_uint64_t max_in_table = index diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h index b42c543c095..83bdaa97949 100644 --- a/storage/innobase/include/btr0btr.h +++ b/storage/innobase/include/btr0btr.h @@ -189,13 +189,16 @@ btr_read_autoinc(dict_index_t* index) /** Read the last used AUTO_INCREMENT value from PAGE_ROOT_AUTO_INC, or fall back to MAX(auto_increment_column). -@param[in] table table containing an AUTO_INCREMENT column -@param[in] col_no index of the AUTO_INCREMENT column -@return the AUTO_INCREMENT value -@retval 0 on error or if no AUTO_INCREMENT value was used yet */ -ib_uint64_t -btr_read_autoinc_with_fallback(const dict_table_t* table, unsigned col_no) - MY_ATTRIBUTE((nonnull, warn_unused_result)); +@param table table containing an AUTO_INCREMENT column +@param col_no index of the AUTO_INCREMENT column +@param mysql_version TABLE_SHARE::mysql_version +@param max the maximum value of the AUTO_INCREMENT column +@return the AUTO_INCREMENT value +@retval 0 on error or if no AUTO_INCREMENT value was used yet */ +uint64_t btr_read_autoinc_with_fallback(const dict_table_t *table, + unsigned col_no, ulong mysql_version, + uint64_t max) + MY_ATTRIBUTE((nonnull, warn_unused_result)); /** Write the next available AUTO_INCREMENT value to PAGE_ROOT_AUTO_INC. @param[in,out] index clustered index diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 6332b4af7bd..43316622225 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -2442,6 +2442,9 @@ public: /** @return number of unique columns in FTS_DOC_ID index */ unsigned fts_n_uniq() const { return versioned() ? 2 : 1; } + /** @return the index for that starts with a specific column */ + dict_index_t *get_index(const dict_col_t &col) const; + /** Create metadata. @param name table name @param space tablespace diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 1d26b7a195e..502e01e1adb 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -4531,6 +4531,15 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn) return(DB_ERROR); } + /* If we fail to open a tablespace while looking for FILE_CHECKPOINT, we + set the corruption flag. Specifically, if encryption key is missing, we + would not be able to open an encrypted tablespace and the flag could be + set. */ + if (recv_sys.is_corrupt_fs()) { + mysql_mutex_unlock(&log_sys.mutex); + return DB_ERROR; + } + if (recv_sys.mlog_checkpoint_lsn == 0) { lsn_t scan_lsn = log_sys.log.scanned_lsn; if (!srv_read_only_mode && scan_lsn != checkpoint_lsn) { diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index bbe8eef5770..ebacda9bc51 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -49,6 +49,8 @@ Created 2012-02-08 by Sunny Bains. #include "snappy-c.h" #endif #include "log.h" +#include "table.h" +#include "ha_innodb.h" #include "scope.h" @@ -4246,6 +4248,37 @@ fil_tablespace_iterate( return(err); } +static void row_import_autoinc(dict_table_t *table, row_prebuilt_t *prebuilt, + uint64_t autoinc) +{ + if (!table->persistent_autoinc) + { + ut_ad(!autoinc); + return; + } + + if (autoinc) + { + btr_write_autoinc(dict_table_get_first_index(table), autoinc - 1); + autoinc_set: + table->autoinc= autoinc; + sql_print_information("InnoDB: %`.*s.%`s autoinc value set to " UINT64PF, + int(table->name.dblen()), table->name.m_name, + table->name.basename(), autoinc); + } + else if (TABLE *t= prebuilt->m_mysql_table) + { + if (const Field *ai= t->found_next_number_field) + { + autoinc= 1 + + btr_read_autoinc_with_fallback(table, innodb_col_no(ai), + t->s->mysql_version, + innobase_get_int_col_max_value(ai)); + goto autoinc_set; + } + } +} + /*****************************************************************//** Imports a tablespace. The space id in the .ibd file must match the space id of the table in the data dictionary. @@ -4586,16 +4619,7 @@ row_import_for_mysql( /* Set autoinc value read from .cfg file, if one was specified. Otherwise, read the PAGE_ROOT_AUTO_INC and set it to table autoinc. */ - if (autoinc) { - ib::info() << table->name << " autoinc value set to " - << autoinc; - - table->autoinc = autoinc--; - btr_write_autoinc(dict_table_get_first_index(table), autoinc); - } else if (table->persistent_autoinc) { - autoinc = btr_read_autoinc(dict_table_get_first_index(table)); - table->autoinc = ++autoinc; - } + row_import_autoinc(table, prebuilt, autoinc); return row_import_cleanup(prebuilt, err); } diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 537a2904bf2..01623c8c27a 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1264,6 +1264,36 @@ dberr_t srv_start(bool create_new_db) return srv_init_abort(DB_ERROR); } + /* Open system tablespace and undo spaces. It is a special case for + restore with empty redo log file. We support restore in such case and + proceed after opening system tablespaces. */ + ulint sum_of_new_sizes; + + auto open_system_spaces = [&]() { + ut_ad(!create_new_db); + ut_ad(srv_operation == SRV_OPERATION_RESTORE || + srv_operation == SRV_OPERATION_RESTORE_EXPORT); + + /* Open system tablespace ibdata1. */ + auto err = srv_sys_space.open_or_create( + false, false, &sum_of_new_sizes, &flushed_lsn); + if (err != DB_SUCCESS) { + return srv_init_abort(err); + } + + /* Open data files for system tablespace. */ + if (!fil_system.sys_space->open(false)) { + return srv_init_abort(DB_ERROR); + } + + /* Open undo tablespaces. */ + err = srv_undo_tablespaces_init(false); + if (err != DB_SUCCESS) { + return srv_init_abort(err); + } + return DB_SUCCESS; + }; + std::string logfile0; bool create_new_log = create_new_db; if (create_new_db) { @@ -1286,7 +1316,8 @@ dberr_t srv_start(bool create_new_db) bool log_file_found; if (dberr_t err = find_and_check_log_file(log_file_found)) { if (err == DB_NOT_FOUND) { - return DB_SUCCESS; + /* For restore, we need to continue. */ + return open_system_spaces(); } return srv_init_abort(err); } @@ -1316,8 +1347,6 @@ dberr_t srv_start(bool create_new_db) } /* Open or create the data files. */ - ulint sum_of_new_sizes; - err = srv_sys_space.open_or_create( false, create_new_db, &sum_of_new_sizes, &flushed_lsn); @@ -1365,10 +1394,8 @@ dberr_t srv_start(bool create_new_db) /* Suppress the message about crash recovery. */ flushed_lsn = log_sys.get_lsn(); - goto file_checked; } -file_checked: /* Open data files in the systemtablespace: we keep them open until database shutdown */ ut_d(fil_system.sys_space->recv_size = srv_sys_space_size_debug); diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index a3a4b73628d..642ba26304e 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -45,6 +45,7 @@ C_MODE_END #include "key.h" #include "log.h" #include "sql_parse.h" +#include "mysql/service_print_check_msg.h" #include "debug.h" /* @@ -428,10 +429,8 @@ static void _ma_check_print_msg(HA_CHECK *param, const LEX_CSTRING *msg_type, const char *fmt, va_list args) { THD *thd= (THD *) param->thd; - Protocol *protocol= thd->protocol; - size_t length, msg_length; + size_t msg_length __attribute__((unused)); char msgbuf[MYSQL_ERRMSG_SIZE]; - char name[NAME_LEN * 2 + 2]; if (param->testflag & T_SUPPRESS_ERR_HANDLING) return; @@ -460,27 +459,10 @@ static void _ma_check_print_msg(HA_CHECK *param, const LEX_CSTRING *msg_type, _ma_check_print(param, msg_type, msgbuf); return; } - length= (uint) (strxmov(name, param->db_name, ".", param->table_name, - NullS) - name); - /* - TODO: switch from protocol to push_warning here. The main reason we didn't - it yet is parallel repair, which threads have no THD object accessible via - current_thd. - - Also we likely need to lock mutex here (in both cases with protocol and - push_warning). - */ - protocol->prepare_for_resend(); - protocol->store(name, (uint)length, system_charset_info); - protocol->store(param->op_name, strlen(param->op_name), system_charset_info); - protocol->store(msg_type, system_charset_info); - protocol->store(msgbuf, msg_length, system_charset_info); - if (protocol->write()) - sql_print_error("Failed on my_net_write, writing to stderr instead: %s.%s: %s\n", - param->db_name, param->table_name, msgbuf); - else if (thd->variables.log_warnings > 2) + print_check_msg(thd, param->db_name, param->table_name, + param->op_name, msg_type->str, msgbuf, 0); + if (thd->variables.log_warnings > 2) _ma_check_print(param, msg_type, msgbuf); - return; } diff --git a/storage/perfschema/table_replication_applier_status.h b/storage/perfschema/table_replication_applier_status.h index 4da2087a32a..5e97dba5c45 100644 --- a/storage/perfschema/table_replication_applier_status.h +++ b/storage/perfschema/table_replication_applier_status.h @@ -59,7 +59,7 @@ struct st_row_applier_status { enum_rpl_yes_no service_state; uint remaining_delay; bool remaining_delay_is_set; - ulong count_transactions_retries; + ulonglong count_transactions_retries; }; /** Table PERFORMANCE_SCHEMA.replication_applier_status */