diff --git a/debian/mariadb-server-10.3.postinst b/debian/mariadb-server-10.3.postinst index cedcd75ef46f9..6c63cb3b3e16a 100644 --- a/debian/mariadb-server-10.3.postinst +++ b/debian/mariadb-server-10.3.postinst @@ -249,8 +249,8 @@ EOF ;; triggered) - if [ -x "$(command -v systemctl)" ]; then - systemctl daemon-reload + if [ -d /run/systemd/system ]; then + systemctl --system daemon-reload fi invoke restart ;; diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc index 0335f90682d53..9b0304a6c96b2 100644 --- a/extra/mariabackup/backup_copy.cc +++ b/extra/mariabackup/backup_copy.cc @@ -1063,6 +1063,7 @@ copy_file(ds_ctxt_t *datasink, ds_file_t *dstfile = NULL; datafile_cur_t cursor; xb_fil_cur_result_t res; + DBUG_ASSERT(datasink->datasink->remove); const char *dst_path = (xtrabackup_copy_back || xtrabackup_move_back)? dst_file_path : trim_dotslash(dst_file_path); @@ -1088,6 +1089,7 @@ copy_file(ds_ctxt_t *datasink, if (ds_write(dstfile, cursor.buf, cursor.buf_read)) { goto error; } + DBUG_EXECUTE_IF("copy_file_error", errno=ENOSPC;goto error;); } if (res == XB_FIL_CUR_ERROR) { @@ -1109,6 +1111,7 @@ copy_file(ds_ctxt_t *datasink, error: datafile_close(&cursor); if (dstfile != NULL) { + datasink->datasink->remove(dstfile->path); ds_close(dstfile); } @@ -1153,17 +1156,18 @@ move_file(ds_ctxt_t *datasink, if (my_rename(src_file_path, dst_file_path_abs, MYF(0)) != 0) { if (my_errno == EXDEV) { - bool ret; - ret = copy_file(datasink, src_file_path, - dst_file_path, thread_n); + /* Fallback to copy/unlink */ + if(!copy_file(datasink, src_file_path, + dst_file_path, thread_n)) + return false; msg(thread_n,"Removing %s", src_file_path); if (unlink(src_file_path) != 0) { my_strerror(errbuf, sizeof(errbuf), errno); - msg("Error: unlink %s failed: %s", + msg("Warning: unlink %s failed: %s", src_file_path, errbuf); } - return(ret); + return true; } my_strerror(errbuf, sizeof(errbuf), my_errno); msg("Can not move file %s to %s: %s", diff --git a/extra/mariabackup/datasink.h b/extra/mariabackup/datasink.h index 201bbfd3267a2..5c82556b9ba6e 100644 --- a/extra/mariabackup/datasink.h +++ b/extra/mariabackup/datasink.h @@ -50,9 +50,15 @@ struct datasink_struct { ds_file_t *(*open)(ds_ctxt_t *ctxt, const char *path, MY_STAT *stat); int (*write)(ds_file_t *file, const unsigned char *buf, size_t len); int (*close)(ds_file_t *file); + int (*remove)(const char *path); void (*deinit)(ds_ctxt_t *ctxt); }; + +static inline int dummy_remove(const char *) { + return 0; +} + /* Supported datasink types */ typedef enum { DS_TYPE_STDOUT, diff --git a/extra/mariabackup/ds_archive.cc b/extra/mariabackup/ds_archive.cc index c8fcfa1f5f5ee..3a5081119b358 100644 --- a/extra/mariabackup/ds_archive.cc +++ b/extra/mariabackup/ds_archive.cc @@ -57,6 +57,7 @@ datasink_t datasink_archive = { &archive_open, &archive_write, &archive_close, + &dummy_remove, &archive_deinit }; diff --git a/extra/mariabackup/ds_buffer.cc b/extra/mariabackup/ds_buffer.cc index 720a329c2388c..6e6ec6fcfbc33 100644 --- a/extra/mariabackup/ds_buffer.cc +++ b/extra/mariabackup/ds_buffer.cc @@ -54,6 +54,7 @@ datasink_t datasink_buffer = { &buffer_open, &buffer_write, &buffer_close, + &dummy_remove, &buffer_deinit }; diff --git a/extra/mariabackup/ds_compress.cc b/extra/mariabackup/ds_compress.cc index 487718e2ac084..3c28e55e1fe9d 100644 --- a/extra/mariabackup/ds_compress.cc +++ b/extra/mariabackup/ds_compress.cc @@ -75,6 +75,7 @@ datasink_t datasink_compress = { &compress_open, &compress_write, &compress_close, + &dummy_remove, &compress_deinit }; diff --git a/extra/mariabackup/ds_local.cc b/extra/mariabackup/ds_local.cc index a6d6be988b1ac..189533d734a7b 100644 --- a/extra/mariabackup/ds_local.cc +++ b/extra/mariabackup/ds_local.cc @@ -43,12 +43,18 @@ static int local_write(ds_file_t *file, const uchar *buf, size_t len); static int local_close(ds_file_t *file); static void local_deinit(ds_ctxt_t *ctxt); +static int local_remove(const char *path) +{ + return unlink(path); +} + extern "C" { datasink_t datasink_local = { &local_init, &local_open, &local_write, &local_close, + &local_remove, &local_deinit }; } diff --git a/extra/mariabackup/ds_stdout.cc b/extra/mariabackup/ds_stdout.cc index 85dbb83865b84..3b3091bd426a3 100644 --- a/extra/mariabackup/ds_stdout.cc +++ b/extra/mariabackup/ds_stdout.cc @@ -40,6 +40,7 @@ datasink_t datasink_stdout = { &stdout_open, &stdout_write, &stdout_close, + &dummy_remove, &stdout_deinit }; diff --git a/extra/mariabackup/ds_tmpfile.cc b/extra/mariabackup/ds_tmpfile.cc index 22dff165aa0aa..d5316803926c0 100644 --- a/extra/mariabackup/ds_tmpfile.cc +++ b/extra/mariabackup/ds_tmpfile.cc @@ -51,6 +51,7 @@ datasink_t datasink_tmpfile = { &tmpfile_open, &tmpfile_write, &tmpfile_close, + &dummy_remove, &tmpfile_deinit }; diff --git a/extra/mariabackup/ds_xbstream.cc b/extra/mariabackup/ds_xbstream.cc index 5a753b0847482..daf1cc7303884 100644 --- a/extra/mariabackup/ds_xbstream.cc +++ b/extra/mariabackup/ds_xbstream.cc @@ -50,6 +50,7 @@ datasink_t datasink_xbstream = { &xbstream_open, &xbstream_write, &xbstream_close, + &dummy_remove, &xbstream_deinit }; diff --git a/extra/mariabackup/innobackupex.cc b/extra/mariabackup/innobackupex.cc index f0e9c06b3555d..be8659ab82682 100644 --- a/extra/mariabackup/innobackupex.cc +++ b/extra/mariabackup/innobackupex.cc @@ -41,6 +41,7 @@ Street, Fifth Floor, Boston, MA 02110-1335 USA #include #include +#include #include #include #include @@ -206,7 +207,8 @@ enum innobackupex_options OPT_STREAM, OPT_TABLES_FILE, OPT_THROTTLE, - OPT_USE_MEMORY + OPT_USE_MEMORY, + OPT_INNODB_FORCE_RECOVERY, }; ibx_mode_t ibx_mode = IBX_MODE_BACKUP; @@ -624,6 +626,16 @@ static struct my_option ibx_long_options[] = 0, GET_LL, REQUIRED_ARG, 100*1024*1024L, 1024*1024L, LONGLONG_MAX, 0, 1024*1024L, 0}, + {"innodb-force-recovery", OPT_INNODB_FORCE_RECOVERY, + "This option starts up the embedded InnoDB instance in crash " + "recovery mode to ignore page corruption; should be used " + "with the \"--apply-log\" option, in emergencies only. The " + "default value is 0. Refer to \"innodb_force_recovery\" server " + "system variable documentation for more details.", + (uchar*)&xtrabackup_innodb_force_recovery, + (uchar*)&xtrabackup_innodb_force_recovery, + 0, GET_ULONG, OPT_ARG, 0, 0, SRV_FORCE_IGNORE_CORRUPT, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -669,6 +681,7 @@ innobackupex [--compress] [--compress-threads=NUMBER-OF-THREADS] [--compress-chu innobackupex --apply-log [--use-memory=B]\n\ [--defaults-file=MY.CNF]\n\ [--export] [--ibbackup=IBBACKUP-BINARY]\n\ + [--innodb-force-recovery=1]\n\ BACKUP-DIR\n\ \n\ innobackupex --copy-back [--defaults-file=MY.CNF] [--defaults-group=GROUP-NAME] BACKUP-DIR\n\ @@ -892,6 +905,12 @@ ibx_init() opt_user = opt_ibx_user; opt_password = opt_ibx_password; +#if !defined(DONT_USE_MYSQL_PWD) + if (!opt_password) + { + opt_password=getenv("MYSQL_PWD"); + } +#endif opt_host = opt_ibx_host; opt_defaults_group = opt_ibx_defaults_group; opt_socket = opt_ibx_socket; diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 7872438d51c57..ebb5f7f367373 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -4,7 +4,7 @@ MariaBackup: hot backup tool for InnoDB Originally Created 3/3/2009 Yasufumi Kinoshita Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko, Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz. -(c) 2017, 2020, MariaDB Corporation. +(c) 2017, 2021, MariaDB Corporation. Portions written by Marko Mäkelä. This program is free software; you can redistribute it and/or modify @@ -267,6 +267,12 @@ static char *xtrabackup_debug_sync = NULL; my_bool xtrabackup_incremental_force_scan = FALSE; +/* + * Ignore corrupt pages (disabled by default; used + * by "innobackupex" as a command line argument). + */ +ulong xtrabackup_innodb_force_recovery = 0; + /* The flushed lsn which is read from data files */ lsn_t flushed_lsn= 0; @@ -1043,7 +1049,8 @@ enum options_xtrabackup OPT_ROCKSDB_DATADIR, OPT_BACKUP_ROCKSDB, OPT_XTRA_CHECK_PRIVILEGES, - OPT_XB_IGNORE_INNODB_PAGE_CORRUPTION + OPT_XB_IGNORE_INNODB_PAGE_CORRUPTION, + OPT_INNODB_FORCE_RECOVERY }; struct my_option xb_client_options[]= { @@ -1671,6 +1678,13 @@ struct my_option xb_server_options[] = &opt_check_privileges, &opt_check_privileges, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 }, + {"innodb_force_recovery", OPT_INNODB_FORCE_RECOVERY, + "(for --prepare): Crash recovery mode (ignores " + "page corruption; for emergencies only).", + (G_PTR*)&srv_force_recovery, + (G_PTR*)&srv_force_recovery, + 0, GET_ULONG, OPT_ARG, 0, 0, SRV_FORCE_IGNORE_CORRUPT, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -1802,24 +1816,26 @@ static int prepare_export() " --defaults-extra-file=./backup-my.cnf --defaults-group-suffix=%s --datadir=." " --innodb --innodb-fast-shutdown=0 --loose-partition" " --innodb_purge_rseg_truncate_frequency=1 --innodb-buffer-pool-size=%llu" - " --console --skip-log-error --skip-log-bin --bootstrap < " + " --console --skip-log-error --skip-log-bin --bootstrap %s < " BOOTSTRAP_FILENAME IF_WIN("\"",""), - mariabackup_exe, + mariabackup_exe, orig_argv1, (my_defaults_group_suffix?my_defaults_group_suffix:""), - xtrabackup_use_memory); + xtrabackup_use_memory, + (srv_force_recovery ? "--innodb-force-recovery=1" : "")); } else { - sprintf(cmdline, + snprintf(cmdline, sizeof cmdline, IF_WIN("\"","") "\"%s\" --mysqld" " --defaults-file=./backup-my.cnf --defaults-group-suffix=%s --datadir=." " --innodb --innodb-fast-shutdown=0 --loose-partition" " --innodb_purge_rseg_truncate_frequency=1 --innodb-buffer-pool-size=%llu" - " --console --log-error= --skip-log-bin --bootstrap < " + " --console --log-error= --skip-log-bin --bootstrap %s < " BOOTSTRAP_FILENAME IF_WIN("\"",""), mariabackup_exe, (my_defaults_group_suffix?my_defaults_group_suffix:""), - xtrabackup_use_memory); + xtrabackup_use_memory, + (srv_force_recovery ? "--innodb-force-recovery=1" : "")); } msg("Prepare export : executing %s\n", cmdline); @@ -1980,6 +1996,13 @@ xb_get_one_option(int optid, ADD_PRINT_PARAM_OPT(innobase_buffer_pool_filename); break; + case OPT_INNODB_FORCE_RECOVERY: + + if (srv_force_recovery) { + ADD_PRINT_PARAM_OPT(srv_force_recovery); + } + break; + case OPT_XTRA_TARGET_DIR: strmake(xtrabackup_real_target_dir,argument, sizeof(xtrabackup_real_target_dir)-1); xtrabackup_target_dir= xtrabackup_real_target_dir; @@ -2234,6 +2257,29 @@ static bool innodb_init_param() srv_undo_dir = (char*) "."; } + compile_time_assert(SRV_FORCE_IGNORE_CORRUPT == 1); + + /* + * This option can be read both from the command line, and the + * defaults file. The assignment should account for both cases, + * and for "--innobackupex". Since the command line argument is + * parsed after the defaults file, it takes precedence. + */ + if (xtrabackup_innodb_force_recovery) { + srv_force_recovery = xtrabackup_innodb_force_recovery; + } + + if (srv_force_recovery >= SRV_FORCE_IGNORE_CORRUPT) { + if (!xtrabackup_prepare) { + msg("mariabackup: The option \"innodb_force_recovery\"" + " should only be used with \"%s\".", + (innobackupex_mode ? "--apply-log" : "--prepare")); + goto error; + } else { + msg("innodb_force_recovery = %lu", srv_force_recovery); + } + } + #ifdef _WIN32 srv_use_native_aio = TRUE; #endif diff --git a/extra/mariabackup/xtrabackup.h b/extra/mariabackup/xtrabackup.h index 827def4be5b46..061057a604f16 100644 --- a/extra/mariabackup/xtrabackup.h +++ b/extra/mariabackup/xtrabackup.h @@ -173,6 +173,8 @@ enum binlog_info_enum { BINLOG_INFO_OFF, BINLOG_INFO_ON, extern ulong opt_binlog_info; +extern ulong xtrabackup_innodb_force_recovery; + void xtrabackup_io_throttling(void); my_bool xb_write_delta_metadata(const char *filename, const xb_delta_info_t *info); diff --git a/mysql-test/main/userstat.result b/mysql-test/main/userstat.result index 12f73bdc6c660..7c8c4057e041f 100644 --- a/mysql-test/main/userstat.result +++ b/mysql-test/main/userstat.result @@ -241,6 +241,8 @@ create function f() returns int return (select 1 from performance_schema.threads set global userstat= 1; select f() from information_schema.table_statistics; ERROR 21000: Subquery returns more than 1 row +select f() from information_schema.index_statistics; +ERROR 21000: Subquery returns more than 1 row set global userstat= 0; drop function f; # diff --git a/mysql-test/main/userstat.test b/mysql-test/main/userstat.test index cc7ddd58e1131..6d486810db12b 100644 --- a/mysql-test/main/userstat.test +++ b/mysql-test/main/userstat.test @@ -121,6 +121,8 @@ create function f() returns int return (select 1 from performance_schema.threads set global userstat= 1; --error ER_SUBQUERY_NO_1_ROW select f() from information_schema.table_statistics; +--error ER_SUBQUERY_NO_1_ROW +select f() from information_schema.index_statistics; set global userstat= 0; drop function f; diff --git a/mysql-test/suite/galera/r/galera_virtual_blob.result b/mysql-test/suite/galera/r/galera_virtual_blob.result new file mode 100644 index 0000000000000..91952b1d52db9 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_virtual_blob.result @@ -0,0 +1,19 @@ +CREATE TABLE t (f INT GENERATED ALWAYS AS (a+b)VIRTUAL,a INT,b INT,h BLOB); +INSERT INTO t (a,b)VALUES(0,0), (0,0), (0,0), (0,0), (0,0); +SELECT * from t; +f a b h +0 0 0 NULL +0 0 0 NULL +0 0 0 NULL +0 0 0 NULL +0 0 0 NULL +connection node_2; +SELECT * from t; +f a b h +0 0 0 NULL +0 0 0 NULL +0 0 0 NULL +0 0 0 NULL +0 0 0 NULL +connection node_1; +DROP TABLE t; diff --git a/mysql-test/suite/galera/t/galera_virtual_blob.test b/mysql-test/suite/galera/t/galera_virtual_blob.test new file mode 100644 index 0000000000000..a10e3025668bb --- /dev/null +++ b/mysql-test/suite/galera/t/galera_virtual_blob.test @@ -0,0 +1,10 @@ +--source include/galera_cluster.inc + +CREATE TABLE t (f INT GENERATED ALWAYS AS (a+b)VIRTUAL,a INT,b INT,h BLOB); +INSERT INTO t (a,b)VALUES(0,0), (0,0), (0,0), (0,0), (0,0); +SELECT * from t; + +--connection node_2 +SELECT * from t; +--connection node_1 +DROP TABLE t; diff --git a/mysql-test/suite/innodb/r/innodb_buffer_pool_fail.result b/mysql-test/suite/innodb/r/innodb_buffer_pool_fail.result new file mode 100644 index 0000000000000..9f6959cb9934d --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_buffer_pool_fail.result @@ -0,0 +1,7 @@ +call mtr.add_suppression("InnoDB: Cannot allocate memory for the buffer pool"); +call mtr.add_suppression("InnoDB: Plugin initialization aborted at srv0start.cc.*"); +call mtr.add_suppression("Plugin 'InnoDB' init function returned error."); +call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed."); +# +# MDEV-25019 memory allocation failures during startup cause server failure in different, confusing ways +# diff --git a/mysql-test/suite/innodb/t/innodb_buffer_pool_fail.test b/mysql-test/suite/innodb/t/innodb_buffer_pool_fail.test new file mode 100644 index 0000000000000..1d938e12e7836 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_buffer_pool_fail.test @@ -0,0 +1,11 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +call mtr.add_suppression("InnoDB: Cannot allocate memory for the buffer pool"); +call mtr.add_suppression("InnoDB: Plugin initialization aborted at srv0start.cc.*"); +call mtr.add_suppression("Plugin 'InnoDB' init function returned error."); +call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed."); +--echo # +--echo # MDEV-25019 memory allocation failures during startup cause server failure in different, confusing ways +--echo # +let restart_parameters=--debug_dbug="+d,ib_buf_chunk_init_fails"; +--source include/restart_mysqld.inc diff --git a/mysql-test/suite/innodb_fts/r/fulltext.result b/mysql-test/suite/innodb_fts/r/fulltext.result index c3345548c0d61..abcdebca01d04 100644 --- a/mysql-test/suite/innodb_fts/r/fulltext.result +++ b/mysql-test/suite/innodb_fts/r/fulltext.result @@ -690,6 +690,19 @@ FTS_DOC_ID t 3 foo DROP TABLE t; # +# MDEV-25295 Aborted FTS_DOC_ID_INDEX considered as +# existing FTS_DOC_ID_INDEX during DDL +# +SET sql_mode=''; +CREATE TABLE t1 (FTS_DOC_ID BIGINT UNSIGNED NOT NULL,title CHAR(1),body TEXT)engine=innodb; +INSERT INTO t1 (FTS_DOC_ID,title,body)VALUES(1,0,0), (1,0,0); +CREATE FULLTEXT INDEX idx1 ON t1 (title,body); +ERROR 23000: Duplicate entry '' for key '*UNKNOWN*' +CREATE FULLTEXT INDEX idx1 ON t1 (title,body); +ERROR 23000: Duplicate entry '' for key '*UNKNOWN*' +DROP TABLE t1; +SET sql_mode = DEFAULT; +# # MDEV-25070 SIGSEGV in fts_create_in_mem_aux_table # CREATE TABLE t1 (a CHAR, FULLTEXT KEY(a)) ENGINE=InnoDB; @@ -705,3 +718,4 @@ t1 CREATE TABLE `t1` ( FULLTEXT KEY `a_2` (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 DROP TABLE t1; +# End of 10.3 tests diff --git a/mysql-test/suite/innodb_fts/t/fulltext.test b/mysql-test/suite/innodb_fts/t/fulltext.test index 560ee8f96f260..f3bcaaec5cc2f 100644 --- a/mysql-test/suite/innodb_fts/t/fulltext.test +++ b/mysql-test/suite/innodb_fts/t/fulltext.test @@ -718,6 +718,20 @@ while ($N) DROP TABLE t; +--echo # +--echo # MDEV-25295 Aborted FTS_DOC_ID_INDEX considered as +--echo # existing FTS_DOC_ID_INDEX during DDL +--echo # +SET sql_mode=''; +CREATE TABLE t1 (FTS_DOC_ID BIGINT UNSIGNED NOT NULL,title CHAR(1),body TEXT)engine=innodb; +INSERT INTO t1 (FTS_DOC_ID,title,body)VALUES(1,0,0), (1,0,0); +--error ER_DUP_ENTRY +CREATE FULLTEXT INDEX idx1 ON t1 (title,body); +--error ER_DUP_ENTRY +CREATE FULLTEXT INDEX idx1 ON t1 (title,body); +DROP TABLE t1; +SET sql_mode = DEFAULT; + --echo # --echo # MDEV-25070 SIGSEGV in fts_create_in_mem_aux_table --echo # @@ -726,3 +740,5 @@ ALTER TABLE t1 DISCARD TABLESPACE; ALTER TABLE t1 ADD FULLTEXT INDEX (a); SHOW CREATE TABLE t1; DROP TABLE t1; + +--echo # End of 10.3 tests diff --git a/mysql-test/suite/mariabackup/error_during_copyback.result b/mysql-test/suite/mariabackup/error_during_copyback.result new file mode 100644 index 0000000000000..9b12c1135d2c3 --- /dev/null +++ b/mysql-test/suite/mariabackup/error_during_copyback.result @@ -0,0 +1,9 @@ +CREATE TABLE t(i INT) ENGINE INNODB; +INSERT INTO t VALUES(1); +# xtrabackup backup +# xtrabackup prepare +# restart server +SELECT * FROM t; +i +1 +DROP TABLE t; diff --git a/mysql-test/suite/mariabackup/error_during_copyback.test b/mysql-test/suite/mariabackup/error_during_copyback.test new file mode 100644 index 0000000000000..3ec9fbfc3c3b4 --- /dev/null +++ b/mysql-test/suite/mariabackup/error_during_copyback.test @@ -0,0 +1,25 @@ +--source include/have_debug.inc +CREATE TABLE t(i INT) ENGINE INNODB; +INSERT INTO t VALUES(1); +echo # xtrabackup backup; +let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir; +--enable_result_log +echo # xtrabackup prepare; +--disable_result_log +exec $XTRABACKUP --prepare --target-dir=$targetdir; +let $_datadir= `SELECT @@datadir`; +--source include/shutdown_mysqld.inc +rmdir $_datadir; +error 1; +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --copy-back --datadir=$_datadir --target-dir=$targetdir --dbug=+d,copy_file_error; +list_files $_datadir; +rmdir $_datadir; +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --copy-back --datadir=$_datadir --target-dir=$targetdir; +echo # restart server; +--source include/start_mysqld.inc +SELECT * FROM t; +DROP TABLE t; +rmdir $targetdir; + diff --git a/mysql-test/suite/mariabackup/innodb_force_recovery.result b/mysql-test/suite/mariabackup/innodb_force_recovery.result new file mode 100644 index 0000000000000..94a265cfabe08 --- /dev/null +++ b/mysql-test/suite/mariabackup/innodb_force_recovery.result @@ -0,0 +1,26 @@ +CREATE TABLE t(i INT) ENGINE INNODB; +INSERT INTO t VALUES(1); +# "innodb_force_recovery=1" should be allowed with "--prepare" only (mariabackup) +FOUND 1 /should only be used with "--prepare"/ in backup.log +# "innodb_force_recovery=1" should be allowed with "--apply-log" only (innobackupex) +FOUND 1 /should only be used with "--apply-log"/ in backup.log +# "innodb_force_recovery" should be limited to "SRV_FORCE_IGNORE_CORRUPT" (mariabackup) +FOUND 1 /innodb_force_recovery = 1/ in backup.log +# "innodb_force_recovery" should be limited to "SRV_FORCE_IGNORE_CORRUPT" (innobackupex) +FOUND 1 /innodb_force_recovery = 1/ in backup.log +# "innodb_force_recovery" should be read from "backup-my.cnf" (mariabackup) +FOUND 1 /innodb_force_recovery = 1/ in backup.log +# "innodb_force_recovery=1" should be read from "backup-my.cnf" (innobackupex) +FOUND 1 /innodb_force_recovery = 1/ in backup.log +# "innodb_force_recovery" from the command line should override "backup-my.cnf" (mariabackup) +NOT FOUND /innodb_force_recovery = 1/ in backup.log +# "innodb_force_recovery" from the command line should override "backup-my.cnf" (innobackupex) +NOT FOUND /innodb_force_recovery = 1/ in backup.log +# shutdown server +# remove datadir +# xtrabackup move back +# restart server +SELECT * FROM t; +i +1 +DROP TABLE t; diff --git a/mysql-test/suite/mariabackup/innodb_force_recovery.test b/mysql-test/suite/mariabackup/innodb_force_recovery.test new file mode 100644 index 0000000000000..3a7b3c6106c6d --- /dev/null +++ b/mysql-test/suite/mariabackup/innodb_force_recovery.test @@ -0,0 +1,138 @@ +# This test checks if "innodb_force_recovery" is only allowed with "--prepare" +# (for mariabackup) and "--apply-log" (for innobackupex), and is limited to +# "SRV_FORCE_IGNORE_CORRUPT" only. + +# Setup. +--source include/have_innodb.inc + +--let targetdir=$MYSQLTEST_VARDIR/tmp/backup +--let backuplog=$MYSQLTEST_VARDIR/tmp/backup.log + +CREATE TABLE t(i INT) ENGINE INNODB; +INSERT INTO t VALUES(1); + +# Check for command line arguments. +--echo # "innodb_force_recovery=1" should be allowed with "--prepare" only (mariabackup) +--disable_result_log +--error 1 +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --innodb-force-recovery=1 --target-dir=$targetdir >$backuplog; +--enable_result_log +--let SEARCH_PATTERN=should only be used with "--prepare" +--let SEARCH_FILE=$backuplog +--source include/search_pattern_in_file.inc + +--echo # "innodb_force_recovery=1" should be allowed with "--apply-log" only (innobackupex) +--disable_result_log +--error 1 +exec $XTRABACKUP --innobackupex --defaults-file=$MYSQLTEST_VARDIR/my.cnf --no-timestamp --innodb-force-recovery=1 $targetdir >$backuplog; +--enable_result_log +--let SEARCH_PATTERN=should only be used with "--apply-log" +--let SEARCH_FILE=$backuplog +--source include/search_pattern_in_file.inc + +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir; +--enable_result_log +--echo # "innodb_force_recovery" should be limited to "SRV_FORCE_IGNORE_CORRUPT" (mariabackup) +--disable_result_log +exec $XTRABACKUP --prepare --innodb-force-recovery=2 --target-dir=$targetdir >$backuplog; +--enable_result_log +--let SEARCH_PATTERN=innodb_force_recovery = 1 +--let SEARCH_FILE=$backuplog +--source include/search_pattern_in_file.inc +rmdir $targetdir; + +--disable_result_log +exec $XTRABACKUP --innobackupex --defaults-file=$MYSQLTEST_VARDIR/my.cnf --no-timestamp $targetdir; +--enable_result_log +--echo # "innodb_force_recovery" should be limited to "SRV_FORCE_IGNORE_CORRUPT" (innobackupex) +--disable_result_log +exec $XTRABACKUP --innobackupex --apply-log --innodb-force-recovery=2 $targetdir >$backuplog; +--enable_result_log +--let SEARCH_PATTERN=innodb_force_recovery = 1 +--let SEARCH_FILE=$backuplog +--source include/search_pattern_in_file.inc +rmdir $targetdir; + +# Check for default file ("backup-my.cnf"). +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir; +--enable_result_log +perl; +my $cfg_path="$ENV{'targetdir'}/backup-my.cnf"; +open(my $fd, '>>', "$cfg_path"); +print $fd "innodb_force_recovery=1\n"; +close $fd; +EOF +--echo # "innodb_force_recovery" should be read from "backup-my.cnf" (mariabackup) +--disable_result_log +exec $XTRABACKUP --defaults-file=$targetdir/backup-my.cnf --prepare --export --target-dir=$targetdir >$backuplog; +--enable_result_log +--let SEARCH_PATTERN=innodb_force_recovery = 1 +--let SEARCH_FILE=$backuplog +--source include/search_pattern_in_file.inc +rmdir $targetdir; + +--disable_result_log +exec $XTRABACKUP --innobackupex --defaults-file=$MYSQLTEST_VARDIR/my.cnf --no-timestamp $targetdir; +--enable_result_log +perl; +my $cfg_path="$ENV{'targetdir'}/backup-my.cnf"; +open(my $fd, '>>', "$cfg_path"); +print $fd "innodb_force_recovery=2\n"; +close $fd; +EOF +--echo # "innodb_force_recovery=1" should be read from "backup-my.cnf" (innobackupex) +--disable_result_log +exec $XTRABACKUP --innobackupex --defaults-file=$targetdir/backup-my.cnf --apply-log --export $targetdir >$backuplog; +--enable_result_log +--let SEARCH_PATTERN=innodb_force_recovery = 1 +--let SEARCH_FILE=$backuplog +--source include/search_pattern_in_file.inc +rmdir $targetdir; + +# Check for command line argument precedence. +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir; +--enable_result_log +perl; +my $cfg_path="$ENV{'targetdir'}/backup-my.cnf"; +open(my $fd, '>>', "$cfg_path"); +print $fd "innodb_force_recovery=1\n"; +close $fd; +EOF +--echo # "innodb_force_recovery" from the command line should override "backup-my.cnf" (mariabackup) +--disable_result_log +exec $XTRABACKUP --defaults-file=$targetdir/backup-my.cnf --prepare --innodb-force-recovery=0 --target-dir=$targetdir >$backuplog; +--enable_result_log +--let SEARCH_PATTERN=innodb_force_recovery = 1 +--let SEARCH_FILE=$backuplog +--source include/search_pattern_in_file.inc +rmdir $targetdir; + +--disable_result_log +exec $XTRABACKUP --innobackupex --defaults-file=$MYSQLTEST_VARDIR/my.cnf --no-timestamp $targetdir; +--enable_result_log +perl; +my $cfg_path="$ENV{'targetdir'}/backup-my.cnf"; +open(my $fd, '>>', "$cfg_path"); +print $fd "innodb_force_recovery=2\n"; +close $fd; +EOF +--echo # "innodb_force_recovery" from the command line should override "backup-my.cnf" (innobackupex) +--disable_result_log +exec $XTRABACKUP --innobackupex --defaults-file=$targetdir/backup-my.cnf --apply-log --innodb-force-recovery=0 --export $targetdir >$backuplog; +--enable_result_log +--let SEARCH_PATTERN=innodb_force_recovery = 1 +--let SEARCH_FILE=$backuplog +--source include/search_pattern_in_file.inc + +--source include/restart_and_restore.inc + +# Check for restore. +SELECT * FROM t; + +# Clean-up. +DROP TABLE t; +--rmdir $targetdir +--remove_file $backuplog diff --git a/plugin/userstat/index_stats.cc b/plugin/userstat/index_stats.cc index 0528507c50ed6..da0d4060b9801 100644 --- a/plugin/userstat/index_stats.cc +++ b/plugin/userstat/index_stats.cc @@ -28,7 +28,7 @@ static int index_stats_fill(THD *thd, TABLE_LIST *tables, COND *cond) tmp_table.grant.privilege= 0; if (check_access(thd, SELECT_ACL, tmp_table.db.str, &tmp_table.grant.privilege, NULL, 0, 1) || - check_grant(thd, SELECT_ACL, &tmp_table, 1, UINT_MAX, 1)) + check_grant(thd, SELECT_ACL, &tmp_table, 1, 1, 1)) continue; index_name= tmp_table.table_name.str + tmp_table.table_name.length + 1; diff --git a/sql/spatial.cc b/sql/spatial.cc index 319c1aaaef674..bda64c6d42073 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2002, 2013, Oracle and/or its affiliates. - Copyright (c) 2011, 2013, Monty Program Ab. + Copyright (c) 2011, 2021, 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 @@ -1050,7 +1050,7 @@ double Gis_point::calculate_haversine(const Geometry *g, int *error) { DBUG_ASSERT(sphere_radius > 0); - double x1r= 0.0, x2r= 0.0, y1r= 0.0, y2r= 0.0, dlong, dlat, res; + double x1r, x2r, y1r, y2r; // This check is done only for optimization purposes where we know it will // be one and only one point in Multipoint @@ -1067,31 +1067,39 @@ double Gis_point::calculate_haversine(const Geometry *g, Geometry *gg= Geometry::construct(&gbuff, point_temp, point_size-1); DBUG_ASSERT(gg); if (static_cast(gg)->get_xy_radian(&x2r, &y2r)) + { DBUG_ASSERT(0); + return -1; + } } else { if (static_cast(g)->get_xy_radian(&x2r, &y2r)) + { DBUG_ASSERT(0); + return -1; + } } if (this->get_xy_radian(&x1r, &y1r)) + { DBUG_ASSERT(0); + return -1; + } // Check boundary conditions: longitude[-180,180] if (!((x2r >= -M_PI && x2r <= M_PI) && (x1r >= -M_PI && x1r <= M_PI))) { *error=1; return -1; } - // Check boundary conditions: lattitude[-90,90] + // Check boundary conditions: latitude[-90,90] if (!((y2r >= -M_PI/2 && y2r <= M_PI/2) && (y1r >= -M_PI/2 && y1r <= M_PI/2))) { *error=-1; return -1; } - dlat= sin((y2r - y1r)/2)*sin((y2r - y1r)/2); - dlong= sin((x2r - x1r)/2)*sin((x2r - x1r)/2); - res= 2*sphere_radius*asin((sqrt(dlat + cos(y1r)*cos(y2r)*dlong))); - return res; + double dlat= sin((y2r - y1r)/2)*sin((y2r - y1r)/2); + double dlong= sin((x2r - x1r)/2)*sin((x2r - x1r)/2); + return 2*sphere_radius*asin((sqrt(dlat + cos(y1r)*cos(y2r)*dlong))); } diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index a6fedaed3c2dc..4f30417e23994 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -1905,6 +1905,10 @@ buf_pool_init_instance( ut_free(buf_pool->chunks); buf_pool_mutex_exit(buf_pool); + /* InnoDB should free the mutex which was + created so far before freeing the instance */ + mutex_free(&buf_pool->mutex); + mutex_free(&buf_pool->zip_mutex); return(DB_ERROR); } diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index cf76e3c83cda2..c469055a763ee 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -2518,7 +2518,8 @@ fts_get_max_cache_size( } } else { ib::error() << "(" << error << ") reading max" - " cache config value from config table"; + " cache config value from config table " + << fts_table->table->name; } ut_free(value.f_str); @@ -2691,7 +2692,8 @@ fts_cmp_set_sync_doc_id( } else { *doc_id = 0; - ib::error() << "(" << error << ") while getting next doc id."; + ib::error() << "(" << error << ") while getting next doc id " + "for table " << table->name; fts_sql_rollback(trx); if (error == DB_DEADLOCK) { @@ -2771,7 +2773,8 @@ fts_update_sync_doc_id( cache->synced_doc_id = doc_id; } else { ib::error() << "(" << error << ") while" - " updating last doc id."; + " updating last doc id for table" + << table->name; fts_sql_rollback(trx); } @@ -4021,7 +4024,8 @@ fts_sync_write_words( if (UNIV_UNLIKELY(error != DB_SUCCESS) && !print_error) { ib::error() << "(" << error << ") writing" - " word node to FTS auxiliary index table."; + " word node to FTS auxiliary index table " + << table->name; print_error = TRUE; } } @@ -4176,7 +4180,8 @@ fts_sync_commit( fts_sql_commit(trx); } else { fts_sql_rollback(trx); - ib::error() << "(" << error << ") during SYNC."; + ib::error() << "(" << error << ") during SYNC of " + "table " << sync->table->name; } if (UNIV_UNLIKELY(fts_enable_diag_print) && elapsed_time) { @@ -4947,7 +4952,8 @@ fts_get_rows_count( trx->error_state = DB_SUCCESS; } else { ib::error() << "(" << error - << ") while reading FTS table."; + << ") while reading FTS table " + << table_name; break; /* Exit the loop. */ } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 57d8f23b66288..d943610e2b22d 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -8752,6 +8752,8 @@ wsrep_calc_row_hash( for (uint i = 0; i < table->s->fields; i++) { byte null_byte=0; byte true_byte=1; + ulint col_type; + ulint is_unsigned; const Field* field = table->field[i]; if (!field->stored_in_db()) { @@ -8760,8 +8762,9 @@ wsrep_calc_row_hash( ptr = (const byte*) row + get_field_offset(table, field); len = field->pack_length(); + col_type = get_innobase_type_from_mysql_type(&is_unsigned, field); - switch (prebuilt->table->cols[i].mtype) { + switch (col_type) { case DATA_BLOB: ptr = row_mysql_read_blob_ref(&len, ptr, len); diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 90c8c08578534..94603704324f6 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -2756,9 +2756,11 @@ innobase_fts_check_doc_id_index( for (index = dict_table_get_first_index(table); index; index = dict_table_get_next_index(index)) { + /* Check if there exists a unique index with the name of - FTS_DOC_ID_INDEX_NAME */ - if (innobase_strcasecmp(index->name, FTS_DOC_ID_INDEX_NAME)) { + FTS_DOC_ID_INDEX_NAME and ignore the corrupted index */ + if (index->type & DICT_CORRUPT + || innobase_strcasecmp(index->name, FTS_DOC_ID_INDEX_NAME)) { continue; } diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index bb9f0f086f5b9..f517b49c99900 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2020, MariaDB Corporation. +Copyright (c) 2016, 2021, 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 @@ -4898,6 +4898,13 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space) bitmap_page = ibuf_bitmap_get_map_page( page_id_t(space->id, page_no), page_size, &mtr); + if (!bitmap_page) { + mutex_exit(&ibuf_mutex); + ibuf_exit(&mtr); + mtr_commit(&mtr); + return DB_CORRUPTION; + } + if (buf_is_zeroes(span(bitmap_page, page_size.physical()))) { /* This means we got all-zero page instead of @@ -4920,11 +4927,6 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space) continue; } - if (!bitmap_page) { - mutex_exit(&ibuf_mutex); - return DB_CORRUPTION; - } - for (i = FSP_IBUF_BITMAP_OFFSET + 1; i < page_size.physical(); i++) { diff --git a/storage/innobase/include/btr0bulk.h b/storage/innobase/include/btr0bulk.h index 171e565da8505..afce691de23a4 100644 --- a/storage/innobase/include/btr0bulk.h +++ b/storage/innobase/include/btr0bulk.h @@ -328,6 +328,8 @@ class BtrBulk /** Re-latch all latches */ void latch(); + dict_index_t* index() { return m_index; } + private: /** Insert a tuple to a page in a level @param[in] tuple tuple to insert diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index ecf611209d6e6..6e179e669ec02 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -925,7 +925,7 @@ DECLARE_THREAD(fts_parallel_tokenization)( << " records, the sort queue has " << UT_LIST_GET_LEN(psort_info->fts_doc_list) << " records. But sort cannot get the next" - " records"; + " records during alter table " << table->name; goto exit; } } else if (psort_info->state == FTS_PARENT_EXITING) { @@ -1221,7 +1221,9 @@ row_merge_write_fts_word( if (UNIV_UNLIKELY(error != DB_SUCCESS)) { ib::error() << "Failed to write word to FTS auxiliary" - " index table, error " << error; + " index table " + << ins_ctx->btr_bulk->index()->table->name + << ", error " << error; ret = error; } diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index dc5eee0793b71..7314fd60cd666 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -2108,7 +2108,7 @@ dberr_t srv_start(bool create_new_db) to the data files and truncate or delete the log. Unless --export is specified, no further change to InnoDB files is needed. */ - ut_ad(!srv_force_recovery); + ut_ad(srv_force_recovery <= SRV_FORCE_IGNORE_CORRUPT); ut_ad(srv_n_log_files_found <= 1); ut_ad(recv_no_log_write); buf_flush_sync_all_buf_pools();