diff --git a/client/mysqldump.c b/client/mysqldump.c index 1c6deb1b9fa..e9ab7785531 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1266,8 +1266,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 */ @@ -1280,10 +1281,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) @@ -6220,17 +6218,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", @@ -6239,6 +6232,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) @@ -6317,7 +6323,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 ? @@ -6333,23 +6338,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) @@ -6363,11 +6381,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]); @@ -6388,6 +6401,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/cmake/pcre.cmake b/cmake/pcre.cmake index 3c427b881fc..752f882d4a8 100644 --- a/cmake/pcre.cmake +++ b/cmake/pcre.cmake @@ -4,6 +4,9 @@ SET(WITH_PCRE "auto" CACHE STRING "Which pcre to use (possible values are 'bundled', 'system', or 'auto')") MACRO(BUNDLE_PCRE2) + SET(WITH_PCRE "bundled" CACHE STRING + "Which pcre to use (possible values are 'bundled', 'system', or 'auto')") + SET(dir "${CMAKE_BINARY_DIR}/extra/pcre2") SET(PCRE_INCLUDE_DIRS ${dir}/src/pcre2-build ${dir}/src/pcre2/src) MESSAGE(STATUS "Will download and bundle pcre2") diff --git a/debian/autobake-deb.sh b/debian/autobake-deb.sh index c958c38065f..28ffe15b712 100755 --- a/debian/autobake-deb.sh +++ b/debian/autobake-deb.sh @@ -32,12 +32,11 @@ then # build is not running on Gitlab-CI. sed '/-DPLUGIN_COLUMNSTORE=NO/d' -i debian/rules # Take the files and part of control from MCS directory - if [ ! -f debian/mariadb-plugin-columnstore.install ] - then - cp -v storage/columnstore/columnstore/debian/mariadb-plugin-columnstore.* debian/ - echo >> debian/control - sed "s/-10.6//" > debian/control - fi + cp -v storage/columnstore/columnstore/debian/mariadb-plugin-columnstore.* debian/ + # idempotent, except for the blank line, but that can be tolerated. + sed -e '/Package: mariadb-plugin-columnstore/,/^$/d' -i debian/control + echo >> debian/control + sed "s/-10.6//" > debian/control fi # Look up distro-version specific stuff diff --git a/debian/mariadb-server.install b/debian/mariadb-server.install index 4a849bc2a46..5e8d48bb9b7 100644 --- a/debian/mariadb-server.install +++ b/debian/mariadb-server.install @@ -70,6 +70,7 @@ usr/share/man/man1/myisam_ftdump.1 usr/share/man/man1/myisamchk.1 usr/share/man/man1/myisamlog.1 usr/share/man/man1/myisampack.1 +usr/share/man/man1/wsrep_sst_backup.1 usr/share/man/man1/wsrep_sst_common.1 usr/share/man/man1/wsrep_sst_mariabackup.1 usr/share/man/man1/wsrep_sst_mysqldump.1 diff --git a/debian/mariadb-server.mariadb.init b/debian/mariadb-server.mariadb.init index 960e5de60cf..26439cf44e4 100644 --- a/debian/mariadb-server.mariadb.init +++ b/debian/mariadb-server.mariadb.init @@ -88,7 +88,7 @@ sanity_checks() { # If datadir location is not changed int configuration # then it's not printed with /usr/sbin/mariadbd --print-defaults # then we use 'sane' default. - if [ -z "$datadir"] + if [ -z "$datadir" ] then datadir="/var/lib/mysql" fi diff --git a/debian/rules b/debian/rules index f90d943efc2..b4ca7897dcc 100755 --- a/debian/rules +++ b/debian/rules @@ -98,7 +98,6 @@ endif -DCOMPILATION_COMMENT="mariadb.org binary distribution" \ -DMYSQL_SERVER_SUFFIX="-$(DEB_VERSION_REVISION)" \ -DSYSTEM_TYPE="debian-$(DEB_HOST_GNU_SYSTEM)" \ - -DCMAKE_SYSTEM_PROCESSOR=$(DEB_HOST_ARCH) \ -DBUILD_CONFIG=mysql_release \ -DCONC_DEFAULT_CHARSET=utf8mb4 \ -DPLUGIN_AWS_KEY_MANAGEMENT=NO \ diff --git a/extra/mariabackup/CMakeLists.txt b/extra/mariabackup/CMakeLists.txt index 9b39321628b..f1f62199a09 100644 --- a/extra/mariabackup/CMakeLists.txt +++ b/extra/mariabackup/CMakeLists.txt @@ -56,7 +56,6 @@ ENDIF() MYSQL_ADD_EXECUTABLE(mariadb-backup xtrabackup.cc innobackupex.cc - changed_page_bitmap.cc datasink.cc ds_buffer.cc ds_compress.cc diff --git a/extra/mariabackup/backup_mysql.cc b/extra/mariabackup/backup_mysql.cc index c2f15da48f8..5b98c630030 100644 --- a/extra/mariabackup/backup_mysql.cc +++ b/extra/mariabackup/backup_mysql.cc @@ -47,6 +47,12 @@ Street, Fifth Floor, Boston, MA 02110-1335 USA #include #include #include +#ifdef HAVE_PWD_H +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#include +#endif #include "common.h" #include "xtrabackup.h" #include "srv0srv.h" @@ -65,7 +71,6 @@ char tool_args[2048]; ulong mysql_server_version; /* server capabilities */ -bool have_changed_page_bitmaps = false; bool have_backup_locks = false; bool have_lock_wait_timeout = false; bool have_galera_enabled = false; @@ -92,11 +97,54 @@ MYSQL *mysql_connection; extern my_bool opt_ssl_verify_server_cert, opt_use_ssl; + +/* + get_os_user() + Ressemles read_user_name() from libmariadb/libmariadb/mariadb_lib.c. +*/ + +#if !defined(_WIN32) + +#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL) +struct passwd *getpwuid(uid_t); +char* getlogin(void); +#endif + +static const char *get_os_user() // Posix +{ + if (!geteuid()) + return "root"; +#ifdef HAVE_GETPWUID + struct passwd *pw; + const char *str; + if ((pw= getpwuid(geteuid())) != NULL) + return pw->pw_name; + if ((str= getlogin()) != NULL) + return str; +#endif + if ((str= getenv("USER")) || + (str= getenv("LOGNAME")) || + (str= getenv("LOGIN"))) + return str; + return NULL; +} + +#else + +static const char *get_os_user() // Windows +{ + return getenv("USERNAME"); +} + +#endif // _WIN32 + + MYSQL * xb_mysql_connect() { MYSQL *connection = mysql_init(NULL); char mysql_port_str[std::numeric_limits::digits10 + 3]; + const char *user= opt_user ? opt_user : get_os_user(); sprintf(mysql_port_str, "%d", opt_port); @@ -126,7 +174,7 @@ xb_mysql_connect() msg("Connecting to MariaDB server host: %s, user: %s, password: %s, " "port: %s, socket: %s", opt_host ? opt_host : "localhost", - opt_user ? opt_user : "not set", + user ? user : "not set", opt_password ? "set" : "not set", opt_port != 0 ? mysql_port_str : "not set", opt_socket ? opt_socket : "not set"); @@ -147,7 +195,7 @@ xb_mysql_connect() if (!mysql_real_connect(connection, opt_host ? opt_host : "localhost", - opt_user, + user, opt_password, "" /*database*/, opt_port, opt_socket, 0)) { @@ -512,24 +560,6 @@ Query the server to find out what backup capabilities it supports. bool detect_mysql_capabilities_for_backup() { - const char *query = "SELECT 'INNODB_CHANGED_PAGES', COUNT(*) FROM " - "INFORMATION_SCHEMA.PLUGINS " - "WHERE PLUGIN_NAME LIKE 'INNODB_CHANGED_PAGES'"; - char *innodb_changed_pages = NULL; - mysql_variable vars[] = { - {"INNODB_CHANGED_PAGES", &innodb_changed_pages}, {NULL, NULL}}; - - if (xtrabackup_incremental) { - - read_mysql_variables(mysql_connection, query, vars, true); - - ut_ad(innodb_changed_pages != NULL); - - have_changed_page_bitmaps = (atoi(innodb_changed_pages) == 1); - - free_mysql_variables(vars); - } - /* do some sanity checks */ if (opt_galera_info && !have_galera_enabled) { msg("--galera-info is specified on the command " @@ -1882,18 +1912,6 @@ select_history() return(true); } -bool -flush_changed_page_bitmaps() -{ - if (xtrabackup_incremental && have_changed_page_bitmaps && - !xtrabackup_incremental_force_scan) { - xb_mysql_query(mysql_connection, - "FLUSH NO_WRITE_TO_BINLOG CHANGED_PAGE_BITMAPS", false); - } - return(true); -} - - /*********************************************************************//** Deallocate memory, disconnect from server, etc. @return true on success. */ diff --git a/extra/mariabackup/backup_mysql.h b/extra/mariabackup/backup_mysql.h index 4b08da0b939..039934be02d 100644 --- a/extra/mariabackup/backup_mysql.h +++ b/extra/mariabackup/backup_mysql.h @@ -7,7 +7,6 @@ extern ulong mysql_server_version; /* server capabilities */ -extern bool have_changed_page_bitmaps; extern bool have_backup_locks; extern bool have_lock_wait_timeout; extern bool have_galera_enabled; @@ -35,9 +34,6 @@ capture_tool_command(int argc, char **argv); bool select_history(); -bool -flush_changed_page_bitmaps(); - void backup_cleanup(); diff --git a/extra/mariabackup/changed_page_bitmap.cc b/extra/mariabackup/changed_page_bitmap.cc deleted file mode 100644 index 39a07a25224..00000000000 --- a/extra/mariabackup/changed_page_bitmap.cc +++ /dev/null @@ -1,1040 +0,0 @@ -/****************************************************** -XtraBackup: hot backup tool for InnoDB -(c) 2009-2012 Percona Inc. -Originally Created 3/3/2009 Yasufumi Kinoshita -Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko, -Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz. - -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 Street, Fifth Floor, Boston, MA 02110-1335 USA - -*******************************************************/ - -/* Changed page bitmap implementation */ - -#include "changed_page_bitmap.h" - -#include "common.h" -#include "xtrabackup.h" -#include "srv0srv.h" - -/* TODO: copy-pasted shared definitions from the XtraDB bitmap write code. -Remove these on the first opportunity, i.e. single-binary XtraBackup. */ - -/* log0online.h */ - -/** Single bitmap file information */ -struct log_online_bitmap_file_t { - char name[FN_REFLEN]; /*!< Name with full path */ - pfs_os_file_t file; /*!< Handle to opened file */ - ib_uint64_t size; /*!< Size of the file */ - ib_uint64_t offset; /*!< Offset of the next read, - or count of already-read bytes - */ -}; - -/** A set of bitmap files containing some LSN range */ -struct log_online_bitmap_file_range_t { - size_t count; /*!< Number of files */ - /*!< Dynamically-allocated array of info about individual files */ - struct files_t { - char name[FN_REFLEN];/*!< Name of a file */ - lsn_t start_lsn; /*!< Starting LSN of data in this - file */ - ulong seq_num; /*!< Sequence number of this file */ - } *files; -}; - -/* log0online.c */ - -/** File name stem for bitmap files. */ -static const char* bmp_file_name_stem = "ib_modified_log_"; - -/** The bitmap file block size in bytes. All writes will be multiples of this. - */ -enum { - MODIFIED_PAGE_BLOCK_SIZE = 4096 -}; - -/** Offsets in a file bitmap block */ -enum { - MODIFIED_PAGE_IS_LAST_BLOCK = 0,/* 1 if last block in the current - write, 0 otherwise. */ - MODIFIED_PAGE_START_LSN = 4, /* The starting tracked LSN of this and - other blocks in the same write */ - MODIFIED_PAGE_END_LSN = 12, /* The ending tracked LSN of this and - other blocks in the same write */ - MODIFIED_PAGE_SPACE_ID = 20, /* The space ID of tracked pages in - this block */ - MODIFIED_PAGE_1ST_PAGE_ID = 24, /* The page ID of the first tracked - page in this block */ - MODIFIED_PAGE_BLOCK_UNUSED_1 = 28,/* Unused in order to align the start - of bitmap at 8 byte boundary */ - MODIFIED_PAGE_BLOCK_BITMAP = 32,/* Start of the bitmap itself */ - MODIFIED_PAGE_BLOCK_UNUSED_2 = MODIFIED_PAGE_BLOCK_SIZE - 8, - /* Unused in order to align the end of - bitmap at 8 byte boundary */ - MODIFIED_PAGE_BLOCK_CHECKSUM = MODIFIED_PAGE_BLOCK_SIZE - 4 - /* The checksum of the current block */ -}; - -/** Length of the bitmap data in a block */ -enum { MODIFIED_PAGE_BLOCK_BITMAP_LEN - = MODIFIED_PAGE_BLOCK_UNUSED_2 - MODIFIED_PAGE_BLOCK_BITMAP }; - -/** Length of the bitmap data in a block in page ids */ -enum { MODIFIED_PAGE_BLOCK_ID_COUNT = MODIFIED_PAGE_BLOCK_BITMAP_LEN * 8 }; - -typedef ib_uint64_t bitmap_word_t; - -/****************************************************************//** -Calculate a bitmap block checksum. Algorithm borrowed from -log_block_calc_checksum. -@return checksum */ -UNIV_INLINE -ulint -log_online_calc_checksum( -/*=====================*/ - const byte* block); /*! p2 -*/ -static -int -log_online_compare_bmp_keys( -/*========================*/ - const void* p1, /*! k2_start_page ? 1 : 0; - } - return k1_space < k2_space ? -1 : 1; -} - -/****************************************************************//** -Calculate a bitmap block checksum. Algorithm borrowed from -log_block_calc_checksum. -@return checksum */ -UNIV_INLINE -ulint -log_online_calc_checksum( -/*=====================*/ - const byte* block) /*! 24) { - - sh = 0; - } - } - - return sum; -} - -/****************************************************************//** -Read one bitmap data page and check it for corruption. - -@return TRUE if page read OK, FALSE if I/O error */ -static -ibool -log_online_read_bitmap_page( -/*========================*/ - log_online_bitmap_file_t *bitmap_file, /*!size >= MODIFIED_PAGE_BLOCK_SIZE); - ut_a(bitmap_file->offset - <= bitmap_file->size - MODIFIED_PAGE_BLOCK_SIZE); - ut_a(bitmap_file->offset % MODIFIED_PAGE_BLOCK_SIZE == 0); - if (DB_SUCCESS != - os_file_read(IORequestRead, bitmap_file->file, page, - bitmap_file->offset, MODIFIED_PAGE_BLOCK_SIZE, - nullptr)) { - /* The following call prints an error message */ - os_file_get_last_error(TRUE); - msg("InnoDB: Warning: failed reading changed page bitmap " - "file \'%s\'", bitmap_file->name); - return FALSE; - } - - bitmap_file->offset += MODIFIED_PAGE_BLOCK_SIZE; - ut_ad(bitmap_file->offset <= bitmap_file->size); - - checksum = mach_read_from_4(page + MODIFIED_PAGE_BLOCK_CHECKSUM); - actual_checksum = log_online_calc_checksum(page); - *checksum_ok = (checksum == actual_checksum); - - return TRUE; -} - -/*********************************************************************//** -Check the name of a given file if it's a changed page bitmap file and -return file sequence and start LSN name components if it is. If is not, -the values of output parameters are undefined. - -@return TRUE if a given file is a changed page bitmap file. */ -static -ibool -log_online_is_bitmap_file( -/*======================*/ - const os_file_stat_t* file_info, /*!name) < OS_FILE_MAX_PATH); - - return ((file_info->type == OS_FILE_TYPE_FILE - || file_info->type == OS_FILE_TYPE_LINK) - && (sscanf(file_info->name, "%[a-z_]%lu_" LSN_PF ".xdb", stem, - bitmap_file_seq_num, bitmap_file_start_lsn) == 3) - && (!strcmp(stem, bmp_file_name_stem))); -} - -/*********************************************************************//** -List the bitmap files in srv_data_home and setup their range that contains the -specified LSN interval. This range, if non-empty, will start with a file that -has the greatest LSN equal to or less than the start LSN and will include all -the files up to the one with the greatest LSN less than the end LSN. Caller -must free bitmap_files->files when done if bitmap_files set to non-NULL and -this function returned TRUE. Field bitmap_files->count might be set to a -larger value than the actual count of the files, and space for the unused array -slots will be allocated but cleared to zeroes. - -@return TRUE if succeeded -*/ -static -ibool -log_online_setup_bitmap_file_range( -/*===============================*/ - log_online_bitmap_file_range_t *bitmap_files, /*!= range_start); - - bitmap_files->count = 0; - bitmap_files->files = NULL; - - /* 1st pass: size the info array */ - - bitmap_dir = os_file_opendir(srv_data_home); - if (UNIV_UNLIKELY(bitmap_dir == IF_WIN(INVALID_HANDLE_VALUE, NULL))) { - msg("InnoDB: Error: failed to open bitmap directory \'%s\'", - srv_data_home); - return FALSE; - } - - while (!os_file_readdir_next_file(srv_data_home, bitmap_dir, - &bitmap_dir_file_info)) { - - ulong file_seq_num; - lsn_t file_start_lsn; - - if (!log_online_is_bitmap_file(&bitmap_dir_file_info, - &file_seq_num, - &file_start_lsn) - || file_start_lsn >= range_end) { - - continue; - } - - if (file_seq_num > last_file_seq_num) { - - last_file_seq_num = file_seq_num; - } - - if (file_start_lsn >= range_start - || file_start_lsn == first_file_start_lsn - || first_file_start_lsn > range_start) { - - /* A file that falls into the range */ - - if (file_start_lsn < first_file_start_lsn) { - - first_file_start_lsn = file_start_lsn; - } - if (file_seq_num < first_file_seq_num) { - - first_file_seq_num = file_seq_num; - } - } else if (file_start_lsn > first_file_start_lsn) { - - /* A file that has LSN closer to the range start - but smaller than it, replacing another such file */ - first_file_start_lsn = file_start_lsn; - first_file_seq_num = file_seq_num; - } - } - - if (UNIV_UNLIKELY(os_file_closedir_failed(bitmap_dir))) { - os_file_get_last_error(TRUE); - msg("InnoDB: Error: cannot close \'%s\'",srv_data_home); - return FALSE; - } - - if (first_file_seq_num == ULONG_MAX && last_file_seq_num == 0) { - - bitmap_files->count = 0; - return TRUE; - } - - bitmap_files->count = last_file_seq_num - first_file_seq_num + 1; - - /* 2nd pass: get the file names in the file_seq_num order */ - - bitmap_dir = os_file_opendir(srv_data_home); - if (UNIV_UNLIKELY(bitmap_dir == IF_WIN(INVALID_HANDLE_VALUE, NULL))) { - msg("InnoDB: Error: failed to open bitmap directory \'%s\'", - srv_data_home); - return FALSE; - } - - bitmap_files->files = - static_cast - (malloc(bitmap_files->count * sizeof(bitmap_files->files[0]))); - memset(bitmap_files->files, 0, - bitmap_files->count * sizeof(bitmap_files->files[0])); - - while (!os_file_readdir_next_file(srv_data_home, bitmap_dir, - &bitmap_dir_file_info)) { - - ulong file_seq_num; - lsn_t file_start_lsn; - size_t array_pos; - - if (!log_online_is_bitmap_file(&bitmap_dir_file_info, - &file_seq_num, - &file_start_lsn) - || file_start_lsn >= range_end - || file_start_lsn < first_file_start_lsn) { - - continue; - } - - array_pos = file_seq_num - first_file_seq_num; - if (UNIV_UNLIKELY(array_pos >= bitmap_files->count)) { - - msg("InnoDB: Error: inconsistent bitmap file " - "directory"); - os_file_closedir(bitmap_dir); - free(bitmap_files->files); - return FALSE; - } - - if (file_seq_num > bitmap_files->files[array_pos].seq_num) { - - bitmap_files->files[array_pos].seq_num = file_seq_num; - strncpy(bitmap_files->files[array_pos].name, - bitmap_dir_file_info.name, FN_REFLEN - 1); - bitmap_files->files[array_pos].name[FN_REFLEN - 1] - = '\0'; - bitmap_files->files[array_pos].start_lsn - = file_start_lsn; - } - } - - if (UNIV_UNLIKELY(os_file_closedir_failed(bitmap_dir))) { - os_file_get_last_error(TRUE); - msg("InnoDB: Error: cannot close \'%s\'", srv_data_home); - free(bitmap_files->files); - return FALSE; - } - -#ifdef UNIV_DEBUG - ut_ad(bitmap_files->files[0].seq_num == first_file_seq_num); - - for (size_t i = 1; i < bitmap_files->count; i++) { - if (!bitmap_files->files[i].seq_num) { - - break; - } - ut_ad(bitmap_files->files[i].seq_num - > bitmap_files->files[i - 1].seq_num); - ut_ad(bitmap_files->files[i].start_lsn - >= bitmap_files->files[i - 1].start_lsn); - } -#endif - - return TRUE; -} - -/****************************************************************//** -Open a bitmap file for reading. - -@return whether opened successfully */ -static -bool -log_online_open_bitmap_file_read_only( -/*==================================*/ - const char* name, /*!name, FN_REFLEN, "%s%s", srv_data_home, name); - bitmap_file->file = os_file_create_simple_no_error_handling( - 0, bitmap_file->name, - OS_FILE_OPEN, OS_FILE_READ_ONLY, true, &success); - if (UNIV_UNLIKELY(!success)) { - - /* Here and below assume that bitmap file names do not - contain apostrophes, thus no need for ut_print_filename(). */ - msg("InnoDB: Warning: error opening the changed page " - "bitmap \'%s\'", bitmap_file->name); - return success; - } - - bitmap_file->size = os_file_get_size(bitmap_file->file); - bitmap_file->offset = 0; - -#ifdef __linux__ - posix_fadvise(bitmap_file->file, 0, 0, POSIX_FADV_SEQUENTIAL); - posix_fadvise(bitmap_file->file, 0, 0, POSIX_FADV_NOREUSE); -#endif - - return success; -} - -/****************************************************************//** -Diagnose one or both of the following situations if we read close to -the end of bitmap file: -1) Warn if the remainder of the file is less than one page. -2) Error if we cannot read any more full pages but the last read page -did not have the last-in-run flag set. - -@return FALSE for the error */ -static -ibool -log_online_diagnose_bitmap_eof( -/*===========================*/ - const log_online_bitmap_file_t* bitmap_file, /*!< in: bitmap file */ - ibool last_page_in_run)/*!< in: "last page in - run" flag value in the - last read page */ -{ - /* Check if we are too close to EOF to read a full page */ - if ((bitmap_file->size < MODIFIED_PAGE_BLOCK_SIZE) - || (bitmap_file->offset - > bitmap_file->size - MODIFIED_PAGE_BLOCK_SIZE)) { - - if (UNIV_UNLIKELY(bitmap_file->offset != bitmap_file->size)) { - - /* If we are not at EOF and we have less than one page - to read, it's junk. This error is not fatal in - itself. */ - - msg("InnoDB: Warning: junk at the end of changed " - "page bitmap file \'%s\'.", bitmap_file->name); - } - - if (UNIV_UNLIKELY(!last_page_in_run)) { - - /* We are at EOF but the last read page did not finish - a run */ - /* It's a "Warning" here because it's not a fatal error - for the whole server */ - msg("InnoDB: Warning: changed page bitmap " - "file \'%s\' does not contain a complete run " - "at the end.", bitmap_file->name); - return FALSE; - } - } - return TRUE; -} - -/* End of copy-pasted definitions */ - -/** Iterator structure over changed page bitmap */ -struct xb_page_bitmap_range_struct { - const xb_page_bitmap *bitmap; /* Bitmap with data */ - ulint space_id; /* Space id for this - iterator */ - ulint bit_i; /* Bit index of the iterator - position in the current page */ - const ib_rbt_node_t *bitmap_node; /* Current bitmap tree node */ - const byte *bitmap_page; /* Current bitmap page */ - ulint current_page_id;/* Current page id */ -}; - -/****************************************************************//** -Print a diagnostic message on missing bitmap data for an LSN range. */ -static -void -xb_msg_missing_lsn_data( -/*====================*/ - lsn_t missing_interval_start, /*!size >= MODIFIED_PAGE_BLOCK_SIZE); - - *page_end_lsn = 0; - - while ((*page_end_lsn <= lsn) - && (bitmap_file->offset - <= bitmap_file->size - MODIFIED_PAGE_BLOCK_SIZE)) { - - next_to_last_page_ok = last_page_ok; - if (!log_online_read_bitmap_page(bitmap_file, page, - &last_page_ok)) { - - return FALSE; - } - - *page_end_lsn = mach_read_from_8(page + MODIFIED_PAGE_END_LSN); - } - - /* We check two pages here because the last read page already contains - the required LSN data. If the next to the last one page is corrupted, - then we have no way of telling if that page contained the required LSN - range data too */ - return last_page_ok && next_to_last_page_ok; -} - -/****************************************************************//** -Read the disk bitmap and build the changed page bitmap tree for the -LSN interval incremental_lsn to log_sys.next_checkpoint_lsn. - -@return the built bitmap tree or NULL if unable to read the full interval for -any reason. */ -xb_page_bitmap* -xb_page_bitmap_init(void) -/*=====================*/ -{ - log_online_bitmap_file_t bitmap_file; - lsn_t bmp_start_lsn = incremental_lsn; - const lsn_t bmp_end_lsn{log_sys.next_checkpoint_lsn}; - byte page[MODIFIED_PAGE_BLOCK_SIZE]; - lsn_t current_page_end_lsn; - xb_page_bitmap *result; - ibool last_page_in_run= FALSE; - log_online_bitmap_file_range_t bitmap_files; - size_t bmp_i; - ibool last_page_ok = TRUE; - - if (UNIV_UNLIKELY(bmp_start_lsn > bmp_end_lsn)) { - - msg("mariabackup: incremental backup LSN " LSN_PF - " is larger than than the last checkpoint LSN " LSN_PF - , bmp_start_lsn, bmp_end_lsn); - return NULL; - } - - if (!log_online_setup_bitmap_file_range(&bitmap_files, bmp_start_lsn, - bmp_end_lsn)) { - - return NULL; - } - - /* Only accept no bitmap files returned if start LSN == end LSN */ - if (bitmap_files.count == 0 && bmp_end_lsn != bmp_start_lsn) { - - return NULL; - } - - result = rbt_create(MODIFIED_PAGE_BLOCK_SIZE, - log_online_compare_bmp_keys); - - if (bmp_start_lsn == bmp_end_lsn) { - - /* Empty range - empty bitmap */ - return result; - } - - bmp_i = 0; - - if (UNIV_UNLIKELY(bitmap_files.files[bmp_i].start_lsn - > bmp_start_lsn)) { - - /* The 1st file does not have the starting LSN data */ - xb_msg_missing_lsn_data(bmp_start_lsn, - bitmap_files.files[bmp_i].start_lsn); - rbt_free(result); - free(bitmap_files.files); - return NULL; - } - - /* Skip any zero-sized files at the start */ - while ((bmp_i < bitmap_files.count - 1) - && (bitmap_files.files[bmp_i].start_lsn - == bitmap_files.files[bmp_i + 1].start_lsn)) { - - bmp_i++; - } - - /* Is the 1st bitmap file missing? */ - if (UNIV_UNLIKELY(bitmap_files.files[bmp_i].name[0] == '\0')) { - - /* TODO: this is not the exact missing range */ - xb_msg_missing_lsn_data(bmp_start_lsn, bmp_end_lsn); - rbt_free(result); - free(bitmap_files.files); - return NULL; - } - - /* Open the 1st bitmap file */ - if (UNIV_UNLIKELY(!log_online_open_bitmap_file_read_only( - bitmap_files.files[bmp_i].name, - &bitmap_file))) { - - rbt_free(result); - free(bitmap_files.files); - return NULL; - } - - /* If the 1st file is truncated, no data. Not merged with the case - below because zero-length file indicates not a corruption but missing - subsequent files instead. */ - if (UNIV_UNLIKELY(bitmap_file.size < MODIFIED_PAGE_BLOCK_SIZE)) { - - xb_msg_missing_lsn_data(bmp_start_lsn, bmp_end_lsn); - rbt_free(result); - free(bitmap_files.files); - os_file_close(bitmap_file.file); - return NULL; - } - - /* Find the start of the required LSN range in the file */ - if (UNIV_UNLIKELY(!xb_find_lsn_in_bitmap_file(&bitmap_file, page, - ¤t_page_end_lsn, - bmp_start_lsn))) { - - msg("mariabackup: Warning: changed page bitmap file " - "\'%s\' corrupted", bitmap_file.name); - rbt_free(result); - free(bitmap_files.files); - os_file_close(bitmap_file.file); - return NULL; - } - - last_page_in_run - = mach_read_from_4(page + MODIFIED_PAGE_IS_LAST_BLOCK); - - if (UNIV_UNLIKELY(!log_online_diagnose_bitmap_eof(&bitmap_file, - last_page_in_run))) { - - rbt_free(result); - free(bitmap_files.files); - os_file_close(bitmap_file.file); - return NULL; - } - - if (UNIV_UNLIKELY(current_page_end_lsn < bmp_start_lsn)) { - - xb_msg_missing_lsn_data(current_page_end_lsn, bmp_start_lsn); - rbt_free(result); - free(bitmap_files.files); - os_file_close(bitmap_file.file); - return NULL; - } - - /* 1st bitmap page found, add it to the tree. */ - rbt_insert(result, page, page); - - /* Read next pages/files until all required data is read */ - while (last_page_ok - && (current_page_end_lsn < bmp_end_lsn - || (current_page_end_lsn == bmp_end_lsn - && !last_page_in_run))) { - - ib_rbt_bound_t tree_search_pos; - - /* If EOF, advance the file skipping over any empty files */ - while (bitmap_file.size < MODIFIED_PAGE_BLOCK_SIZE - || (bitmap_file.offset - > bitmap_file.size - MODIFIED_PAGE_BLOCK_SIZE)) { - - os_file_close(bitmap_file.file); - - if (UNIV_UNLIKELY( - !log_online_diagnose_bitmap_eof( - &bitmap_file, last_page_in_run))) { - - rbt_free(result); - free(bitmap_files.files); - return NULL; - } - - bmp_i++; - - if (UNIV_UNLIKELY(bmp_i == bitmap_files.count - || (bitmap_files.files[bmp_i].seq_num - == 0))) { - - xb_msg_missing_lsn_data(current_page_end_lsn, - bmp_end_lsn); - rbt_free(result); - free(bitmap_files.files); - return NULL; - } - - /* Is the next file missing? */ - if (UNIV_UNLIKELY(bitmap_files.files[bmp_i].name[0] - == '\0')) { - - /* TODO: this is not the exact missing range */ - xb_msg_missing_lsn_data(bitmap_files.files - [bmp_i - 1].start_lsn, - bmp_end_lsn); - rbt_free(result); - free(bitmap_files.files); - return NULL; - } - - if (UNIV_UNLIKELY( - !log_online_open_bitmap_file_read_only( - bitmap_files.files[bmp_i].name, - &bitmap_file))) { - - rbt_free(result); - free(bitmap_files.files); - return NULL; - } - } - - if (UNIV_UNLIKELY( - !log_online_read_bitmap_page(&bitmap_file, page, - &last_page_ok))) { - - rbt_free(result); - free(bitmap_files.files); - os_file_close(bitmap_file.file); - return NULL; - } - - if (UNIV_UNLIKELY(!last_page_ok)) { - - msg("mariabackup: warning: changed page bitmap file " - "\'%s\' corrupted.", bitmap_file.name); - rbt_free(result); - free(bitmap_files.files); - os_file_close(bitmap_file.file); - return NULL; - } - - /* Merge the current page with an existing page or insert a new - page into the tree */ - - if (!rbt_search(result, &tree_search_pos, page)) { - - /* Merge the bitmap pages */ - byte *existing_page - = rbt_value(byte, tree_search_pos.last); - bitmap_word_t *bmp_word_1 = (bitmap_word_t *) - (existing_page + MODIFIED_PAGE_BLOCK_BITMAP); - bitmap_word_t *bmp_end = (bitmap_word_t *) - (existing_page + MODIFIED_PAGE_BLOCK_UNUSED_2); - bitmap_word_t *bmp_word_2 = (bitmap_word_t *) - (page + MODIFIED_PAGE_BLOCK_BITMAP); - while (bmp_word_1 < bmp_end) { - - *bmp_word_1++ |= *bmp_word_2++; - } - xb_a (bmp_word_1 == bmp_end); - } else { - - /* Add a new page */ - rbt_add_node(result, &tree_search_pos, page); - } - - current_page_end_lsn - = mach_read_from_8(page + MODIFIED_PAGE_END_LSN); - last_page_in_run - = mach_read_from_4(page + MODIFIED_PAGE_IS_LAST_BLOCK); - } - - xb_a (current_page_end_lsn >= bmp_end_lsn); - - free(bitmap_files.files); - os_file_close(bitmap_file.file); - - return result; -} - -/****************************************************************//** -Free the bitmap tree. */ -void -xb_page_bitmap_deinit( -/*==================*/ - xb_page_bitmap* bitmap) /*!bitmap_page has been -already found/bumped by rbt_search()/rbt_next(). - -@return FALSE if no more bitmap data for the range space ID */ -static -ibool -xb_page_bitmap_setup_next_page( -/*===========================*/ - xb_page_bitmap_range* bitmap_range) /*!bitmap_node == NULL) { - - bitmap_range->current_page_id = ULINT_UNDEFINED; - return FALSE; - } - - bitmap_range->bitmap_page = rbt_value(byte, bitmap_range->bitmap_node); - - new_space_id = mach_read_from_4(bitmap_range->bitmap_page - + MODIFIED_PAGE_SPACE_ID); - if (new_space_id != bitmap_range->space_id) { - - /* No more data for the current page id. */ - xb_a(new_space_id > bitmap_range->space_id); - bitmap_range->current_page_id = ULINT_UNDEFINED; - return FALSE; - } - - new_1st_page_id = mach_read_from_4(bitmap_range->bitmap_page + - MODIFIED_PAGE_1ST_PAGE_ID); - xb_a (new_1st_page_id >= bitmap_range->current_page_id - || bitmap_range->current_page_id == ULINT_UNDEFINED); - - bitmap_range->current_page_id = new_1st_page_id; - bitmap_range->bit_i = 0; - - return TRUE; -} - -/** Find the node with the smallest key that greater than equal to search key. -@param[in] tree red-black tree -@param[in] key search key -@return node with the smallest greater-than-or-equal key -@retval NULL if none was found */ -static -const ib_rbt_node_t* -rbt_lower_bound(const ib_rbt_t* tree, const void* key) -{ - ut_ad(!tree->cmp_arg); - const ib_rbt_node_t* ge = NULL; - - for (const ib_rbt_node_t *node = tree->root->left; - node != tree->nil; ) { - int result = tree->compare(node->value, key); - - if (result < 0) { - node = node->right; - } else { - ge = node; - if (result == 0) { - break; - } - - node = node->left; - } - } - - return(ge); -} - -/****************************************************************//** -Set up a new bitmap range iterator over a given space id changed -pages in a given bitmap. - -@return bitmap range iterator */ -xb_page_bitmap_range* -xb_page_bitmap_range_init( -/*======================*/ - xb_page_bitmap* bitmap, /*!< in: bitmap to iterate over */ - ulint space_id) /*!< in: space id */ -{ - byte search_page[MODIFIED_PAGE_BLOCK_SIZE]; - xb_page_bitmap_range *result - = static_cast(malloc(sizeof(*result))); - - memset(result, 0, sizeof(*result)); - result->bitmap = bitmap; - result->space_id = space_id; - result->current_page_id = ULINT_UNDEFINED; - - /* Search for the 1st page for the given space id */ - /* This also sets MODIFIED_PAGE_1ST_PAGE_ID to 0, which is what we - want. */ - memset(search_page, 0, MODIFIED_PAGE_BLOCK_SIZE); - mach_write_to_4(search_page + MODIFIED_PAGE_SPACE_ID, space_id); - - result->bitmap_node = rbt_lower_bound(result->bitmap, search_page); - - xb_page_bitmap_setup_next_page(result); - - return result; -} - -/****************************************************************//** -Get the value of the bitmap->range->bit_i bitmap bit - -@return the current bit value */ -static inline -ibool -is_bit_set( -/*=======*/ - const xb_page_bitmap_range* bitmap_range) /*!< in: bitmap - range */ -{ - return ((*(((bitmap_word_t *)(bitmap_range->bitmap_page - + MODIFIED_PAGE_BLOCK_BITMAP)) - + (bitmap_range->bit_i >> 6))) - & (1ULL << (bitmap_range->bit_i & 0x3F))) ? TRUE : FALSE; -} - -/****************************************************************//** -Get the next page id that has its bit set or cleared, i.e. equal to -bit_value. - -@return page id */ -ulint -xb_page_bitmap_range_get_next_bit( -/*==============================*/ - xb_page_bitmap_range* bitmap_range, /*!< in/out: bitmap range */ - ibool bit_value) /*!< in: bit value */ -{ - if (UNIV_UNLIKELY(bitmap_range->current_page_id - == ULINT_UNDEFINED)) { - - return ULINT_UNDEFINED; - } - - do { - while (bitmap_range->bit_i < MODIFIED_PAGE_BLOCK_ID_COUNT) { - - while (is_bit_set(bitmap_range) != bit_value - && (bitmap_range->bit_i - < MODIFIED_PAGE_BLOCK_ID_COUNT)) { - - bitmap_range->current_page_id++; - bitmap_range->bit_i++; - } - - if (bitmap_range->bit_i - < MODIFIED_PAGE_BLOCK_ID_COUNT) { - - ulint result = bitmap_range->current_page_id; - bitmap_range->current_page_id++; - bitmap_range->bit_i++; - return result; - } - } - - bitmap_range->bitmap_node - = rbt_next(bitmap_range->bitmap, - bitmap_range->bitmap_node); - - } while (xb_page_bitmap_setup_next_page(bitmap_range)); - - return ULINT_UNDEFINED; -} - -/****************************************************************//** -Free the bitmap range iterator. */ -void -xb_page_bitmap_range_deinit( -/*========================*/ - xb_page_bitmap_range* bitmap_range) /*! in/out: bitmap range */ -{ - free(bitmap_range); -} diff --git a/extra/mariabackup/changed_page_bitmap.h b/extra/mariabackup/changed_page_bitmap.h deleted file mode 100644 index 8d5043596bf..00000000000 --- a/extra/mariabackup/changed_page_bitmap.h +++ /dev/null @@ -1,85 +0,0 @@ -/****************************************************** -XtraBackup: hot backup tool for InnoDB -(c) 2009-2012 Percona Inc. -Originally Created 3/3/2009 Yasufumi Kinoshita -Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko, -Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz. - -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 Street, Fifth Floor, Boston, MA 02110-1335 USA - -*******************************************************/ - -/* Changed page bitmap interface */ - -#ifndef XB_CHANGED_PAGE_BITMAP_H -#define XB_CHANGED_PAGE_BITMAP_H - -#include -#include - -/* The changed page bitmap structure */ -typedef ib_rbt_t xb_page_bitmap; - -struct xb_page_bitmap_range_struct; - -/* The bitmap range iterator over one space id */ -typedef struct xb_page_bitmap_range_struct xb_page_bitmap_range; - -/****************************************************************//** -Read the disk bitmap and build the changed page bitmap tree for the -LSN interval incremental_lsn to log_sys.next_checkpoint_lsn. - -@return the built bitmap tree */ -xb_page_bitmap* -xb_page_bitmap_init(void); -/*=====================*/ - -/****************************************************************//** -Free the bitmap tree. */ -void -xb_page_bitmap_deinit( -/*==================*/ - xb_page_bitmap* bitmap); /*!page_size); cursor->read_filter = read_filter; - cursor->read_filter->init(&cursor->read_filter_ctxt, cursor, - node->space->id); + cursor->read_filter->init(&cursor->read_filter_ctxt, cursor); return(XB_FIL_CUR_SUCCESS); } @@ -502,10 +501,6 @@ xb_fil_cur_close( /*=============*/ xb_fil_cur_t *cursor) /*!< in/out: source file cursor */ { - if (cursor->read_filter) { - cursor->read_filter->deinit(&cursor->read_filter_ctxt); - } - aligned_free(cursor->buf); cursor->buf = NULL; diff --git a/extra/mariabackup/fil_cur.h b/extra/mariabackup/fil_cur.h index b7812f6589e..46c8cb03705 100644 --- a/extra/mariabackup/fil_cur.h +++ b/extra/mariabackup/fil_cur.h @@ -27,6 +27,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA #include #include "read_filt.h" +#include "mtr0types.h" #include "srv0start.h" #include "srv0srv.h" #include "xtrabackup.h" diff --git a/extra/mariabackup/read_filt.cc b/extra/mariabackup/read_filt.cc index 589200552a2..c7c0aa555a4 100644 --- a/extra/mariabackup/read_filt.cc +++ b/extra/mariabackup/read_filt.cc @@ -32,29 +32,13 @@ Perform read filter context initialization that is common to all read filters. */ static void -common_init( -/*========*/ +rf_pass_through_init( xb_read_filt_ctxt_t* ctxt, /*!offset = 0; ctxt->data_file_size = cursor->statinfo.st_size; ctxt->buffer_capacity = cursor->buf_size; - ctxt->page_size = cursor->page_size; -} - -/****************************************************************//** -Initialize the pass-through read filter. */ -static -void -rf_pass_through_init( -/*=================*/ - xb_read_filt_ctxt_t* ctxt, /*!offset; *read_batch_len = ctxt->data_file_size - ctxt->offset; - if (*read_batch_len > (ib_int64_t)ctxt->buffer_capacity) { + if (*read_batch_len > (int64_t)ctxt->buffer_capacity) { *read_batch_len = ctxt->buffer_capacity; } ctxt->offset += *read_batch_len; } -/****************************************************************//** -Deinitialize the pass-through read filter. */ -static -void -rf_pass_through_deinit( -/*===================*/ - xb_read_filt_ctxt_t* ctxt __attribute__((unused))) - /*!bitmap_range = xb_page_bitmap_range_init(changed_page_bitmap, - space_id); - ctxt->filter_batch_end = 0; -} - -/****************************************************************//** -Get the next batch of pages for the bitmap read filter. */ -static -void -rf_bitmap_get_next_batch( -/*=====================*/ - xb_read_filt_ctxt_t* ctxt, /*!page_size; - - start_page_id = (ulint)(ctxt->offset / page_size); - - xb_a (ctxt->offset % page_size == 0); - - if (start_page_id == ctxt->filter_batch_end) { - - /* Used up all the previous bitmap range, get some more */ - ulint next_page_id; - - /* Find the next changed page using the bitmap */ - next_page_id = xb_page_bitmap_range_get_next_bit - (ctxt->bitmap_range, TRUE); - - if (next_page_id == ULINT_UNDEFINED) { - *read_batch_len = 0; - return; - } - - ctxt->offset = next_page_id * page_size; - - /* Find the end of the current changed page block by searching - for the next cleared bitmap bit */ - ctxt->filter_batch_end - = xb_page_bitmap_range_get_next_bit(ctxt->bitmap_range, - FALSE); - xb_a(next_page_id < ctxt->filter_batch_end); - } - - *read_batch_start = ctxt->offset; - if (ctxt->filter_batch_end == ULINT_UNDEFINED) { - /* No more cleared bits in the bitmap, need to copy all the - remaining pages. */ - *read_batch_len = ctxt->data_file_size - ctxt->offset; - } else { - *read_batch_len = ctxt->filter_batch_end * page_size - - ctxt->offset; - } - - /* If the page block is larger than the buffer capacity, limit it to - buffer capacity. The subsequent invocations will continue returning - the current block in buffer-sized pieces until ctxt->filter_batch_end - is reached, trigerring the next bitmap query. */ - if (*read_batch_len > (ib_int64_t)ctxt->buffer_capacity) { - *read_batch_len = ctxt->buffer_capacity; - } - - ctxt->offset += *read_batch_len; - xb_a (ctxt->offset % page_size == 0); - xb_a (*read_batch_start % page_size == 0); - xb_a (*read_batch_len % page_size == 0); -} - -/****************************************************************//** -Deinitialize the changed page bitmap-based read filter. */ -static -void -rf_bitmap_deinit( -/*=============*/ - xb_read_filt_ctxt_t* ctxt) /*!bitmap_range); -} - /* The pass-through read filter */ xb_read_filt_t rf_pass_through = { &rf_pass_through_init, &rf_pass_through_get_next_batch, - &rf_pass_through_deinit -}; - -/* The changed page bitmap-based read filter */ -xb_read_filt_t rf_bitmap = { - &rf_bitmap_init, - &rf_bitmap_get_next_batch, - &rf_bitmap_deinit }; diff --git a/extra/mariabackup/read_filt.h b/extra/mariabackup/read_filt.h index 51150705367..caf8ac566e0 100644 --- a/extra/mariabackup/read_filt.h +++ b/extra/mariabackup/read_filt.h @@ -25,42 +25,27 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA #ifndef XB_READ_FILT_H #define XB_READ_FILT_H -#include "changed_page_bitmap.h" - -typedef uint32_t space_id_t; +#include +#include struct xb_fil_cur_t; /* The read filter context */ struct xb_read_filt_ctxt_t { - ib_int64_t offset; /*!< current file offset */ - ib_int64_t data_file_size; /*!< data file size */ + int64_t offset; /*!< current file offset */ + int64_t data_file_size; /*!< data file size */ size_t buffer_capacity;/*!< read buffer capacity */ - space_id_t space_id; /*!< space id */ - /* The following fields used only in bitmap filter */ - /* Move these to union if any other filters are added in future */ - xb_page_bitmap_range *bitmap_range; /*!< changed page bitmap range - iterator for space_id */ - ulint page_size; /*!< page size */ - ulint filter_batch_end;/*!< the ending page id of the - current changed page block in - the bitmap */ - /** TODO: remove this default constructor */ - xb_read_filt_ctxt_t() : page_size(0) {} }; /* The read filter */ struct xb_read_filt_t { void (*init)(xb_read_filt_ctxt_t* ctxt, - const xb_fil_cur_t* cursor, - ulint space_id); + const xb_fil_cur_t* cursor); void (*get_next_batch)(xb_read_filt_ctxt_t* ctxt, - ib_int64_t* read_batch_start, - ib_int64_t* read_batch_len); - void (*deinit)(xb_read_filt_ctxt_t* ctxt); + int64_t* read_batch_start, + int64_t* read_batch_len); }; extern xb_read_filt_t rf_pass_through; -extern xb_read_filt_t rf_bitmap; #endif diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 9a76303f53b..295b7e86204 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -101,7 +101,6 @@ Street, Fifth Floor, Boston, MA 02110-1335 USA #include "ds_buffer.h" #include "ds_tmpfile.h" #include "xbstream.h" -#include "changed_page_bitmap.h" #include "read_filt.h" #include "backup_wsrep.h" #include "innobackupex.h" @@ -155,7 +154,6 @@ char *xtrabackup_incremental; lsn_t incremental_lsn; lsn_t incremental_to_lsn; lsn_t incremental_last_lsn; -xb_page_bitmap *changed_page_bitmap; char *xtrabackup_incremental_basedir; /* for --backup */ char *xtrabackup_extra_lsndir; /* for --backup with --extra-lsndir */ @@ -424,6 +422,8 @@ pthread_cond_t scanned_lsn_cond; /** Store the deferred tablespace name during --backup */ static std::set defer_space_names; +typedef decltype(fil_space_t::id) space_id_t; + typedef std::map space_id_to_name_t; struct ddl_tracker_t { @@ -2419,7 +2419,12 @@ static bool innodb_init() os_file_delete_if_exists_func(ib_logfile0.c_str(), nullptr); os_file_t file= os_file_create_func(ib_logfile0.c_str(), OS_FILE_CREATE, OS_FILE_NORMAL, - OS_DATA_FILE_NO_O_DIRECT, false, &ret); +#if defined _WIN32 || defined HAVE_FCNTL_DIRECT + OS_DATA_FILE_NO_O_DIRECT, +#else + OS_DATA_FILE, +#endif + false, &ret); if (!ret) { invalid_log: @@ -3017,12 +3022,7 @@ static my_bool xtrabackup_copy_datafile(ds_ctxt *ds_data, goto skip; } - if (!changed_page_bitmap) { - read_filter = &rf_pass_through; - } - else { - read_filter = &rf_bitmap; - } + read_filter = &rf_pass_through; res = xb_fil_cur_open(&cursor, read_filter, node, thread_n, ULLONG_MAX); if (res == XB_FIL_CUR_SKIP) { @@ -4787,11 +4787,6 @@ fail: std::thread(log_copying_thread).detach(); - /* FLUSH CHANGED_PAGE_BITMAPS call */ - if (!flush_changed_page_bitmaps()) { - goto fail; - } - ut_a(xtrabackup_parallel > 0); if (xtrabackup_parallel > 1) { @@ -4865,9 +4860,6 @@ fail: goto fail; } - if (changed_page_bitmap) { - xb_page_bitmap_deinit(changed_page_bitmap); - } backup_datasinks.destroy(); msg("Redo log (from LSN " LSN_PF " to " LSN_PF ") was copied.", diff --git a/extra/mariabackup/xtrabackup.h b/extra/mariabackup/xtrabackup.h index d091c4744ab..14036b7a92c 100644 --- a/extra/mariabackup/xtrabackup.h +++ b/extra/mariabackup/xtrabackup.h @@ -24,7 +24,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA #include #include "datasink.h" #include "xbstream.h" -#include "changed_page_bitmap.h" +#include "fil0fil.h" #include #define XB_TOOL_NAME "mariadb-backup" @@ -84,8 +84,6 @@ extern my_bool xb_backup_rocksdb; extern uint opt_protocol; -extern xb_page_bitmap *changed_page_bitmap; - extern char *xtrabackup_incremental; extern my_bool xtrabackup_incremental_force_scan; diff --git a/include/my_rdtsc.h b/include/my_rdtsc.h index 8b9b0046bc0..21e44847d9a 100644 --- a/include/my_rdtsc.h +++ b/include/my_rdtsc.h @@ -111,7 +111,7 @@ C_MODE_START On AARCH64, we use the generic timer base register. We override clang implementation for aarch64 as it access a PMU register which is not guaranteed to be active. - On RISC-V, we use the rdcycle instruction to read from mcycle register. + On RISC-V, we use the rdtime instruction to read from mtime register. Sadly, we have nothing for the Digital Alpha, MIPS, Motorola m68k, HP PA-RISC or other non-mainstream (or obsolete) processors. @@ -211,15 +211,15 @@ static inline ulonglong my_timer_cycles(void) } #elif defined(__riscv) #define MY_TIMER_ROUTINE_CYCLES MY_TIMER_ROUTINE_RISCV - /* Use RDCYCLE (and RDCYCLEH on riscv32) */ + /* Use RDTIME (and RDTIMEH on riscv32) */ { # if __riscv_xlen == 32 ulong result_lo, result_hi0, result_hi1; /* Implemented in assembly because Clang insisted on branching. */ __asm __volatile__( - "rdcycleh %0\n" - "rdcycle %1\n" - "rdcycleh %2\n" + "rdtimeh %0\n" + "rdtime %1\n" + "rdtimeh %2\n" "sub %0, %0, %2\n" "seqz %0, %0\n" "sub %0, zero, %0\n" @@ -228,7 +228,7 @@ static inline ulonglong my_timer_cycles(void) return (static_cast(result_hi1) << 32) | result_lo; # else ulonglong result; - __asm __volatile__("rdcycle %0" : "=r"(result)); + __asm __volatile__("rdtime %0" : "=r"(result)); return result; } # endif 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 9abae740a7b..c8169614de2 100644 --- a/include/service_versions.h +++ b/include/service_versions.h @@ -44,6 +44,7 @@ #define VERSION_wsrep 0x0500 #define VERSION_json 0x0100 #define VERSION_thd_mdl 0x0100 +#define VERSION_print_check_msg 0x0100 #define VERSION_sql_service 0x0101 #define VERSION_provider_bzip2 0x0100 diff --git a/libservices/CMakeLists.txt b/libservices/CMakeLists.txt index 8c559cb07f5..37c24646791 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/man/CMakeLists.txt b/man/CMakeLists.txt index ae308a00392..4c71ccbf048 100644 --- a/man/CMakeLists.txt +++ b/man/CMakeLists.txt @@ -25,7 +25,7 @@ IF(NOT WITHOUT_SERVER) INSTALL_MANPAGES(Server wsrep_sst_rsync.1 wsrep_sst_common.1 wsrep_sst_mariabackup.1 wsrep_sst_mysqldump.1 wsrep_sst_rsync_wan.1 galera_recovery.1 - galera_new_cluster.1) + galera_new_cluster.1 wsrep_sst_backup.1) ENDIF() ENDIF() INSTALL_MANPAGES(Client diff --git a/man/my_print_defaults.1 b/man/my_print_defaults.1 index d519d89ea67..38f2c0a8fe1 100644 --- a/man/my_print_defaults.1 +++ b/man/my_print_defaults.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\fBMY_PRINT_DEFAULTS\fR" "1" "15 May 2020" "MariaDB 10.11" "MariaDB Database System" +.TH "\fBMY_PRINT_DEFAULTS\fR" "1" "18 December 2023" "MariaDB 10.11" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- @@ -146,6 +146,22 @@ In addition to the groups named on the command line, read groups that have the g .sp -1 .IP \(bu 2.3 .\} +.\" my_print_defaults: --mariadbd option +.\" mariadbd option: my_print_defaults +\fB\-\-mariadbd\fR +.sp +Read the same set of groups that the mariadbd binary does. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} + .\" my_print_defaults: --mysqld option .\" mysqld option: my_print_defaults \fB\-\-mysqld\fR diff --git a/man/wsrep_sst_backup.1 b/man/wsrep_sst_backup.1 new file mode 100644 index 00000000000..d7b145575cc --- /dev/null +++ b/man/wsrep_sst_backup.1 @@ -0,0 +1,16 @@ +'\" t +.\" +.TH "\FBWSREP_SST_BACKUP\FR" "1" "22 May 2022" "MariaDB 10\&.3" "MariaDB Database System" +.\" ----------------------------------------------------------------- +.\" * set default formatting +.\" ----------------------------------------------------------------- +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH NAME +wsrep_sst_backup \- backup helper script for the MariaDB Galera Cluster +.SH DESCRIPTION +Use: See source code of script\. +.PP +For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/ diff --git a/mysql-test/include/rpl_clone_slave_using_mariadb-backup.inc b/mysql-test/include/rpl_clone_slave_using_mariadb-backup.inc new file mode 100644 index 00000000000..96fcfa2110a --- /dev/null +++ b/mysql-test/include/rpl_clone_slave_using_mariadb-backup.inc @@ -0,0 +1,297 @@ +if ($cnf == "galera2_to_mariadb") +{ + --let MASTER_MYPORT= $NODE_MYPORT_1 + --connect master, 127.0.0.1, root, , test, $NODE_MYPORT_1 + --connect slave, 127.0.0.1, root, , test, $NODE_MYPORT_3 + --disable_query_log + --replace_result $MASTER_MYPORT ### + --eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$MASTER_MYPORT, MASTER_USE_GTID=NO; + --enable_query_log + START SLAVE; + --source include/wait_for_slave_to_start.inc + + --let XTRABACKUP_BACKUP_OPTIONS=--no-defaults --user=root --host='127.0.0.1' --port=$NODE_MYPORT_3 + --let XTRABACKUP_COPY_BACK_OPTIONS= --no-defaults +} + +if ($cnf == "mariadb_to_mariadb") +{ + --let XTRABACKUP_BACKUP_OPTIONS=--defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group-suffix=.2 + --let XTRABACKUP_COPY_BACK_OPTIONS=--defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group-suffix=.2 +} + +--connection master +--let $MYSQLD_DATADIR_MASTER= `select @@datadir` +--connection slave +--let $MYSQLD_DATADIR_SLAVE= `select @@datadir` + +# This test covers the filename:pos based synchronization +# between the master and the slave. +# If we ever need to test a GTID based synchronization, +# it should be done in a separate test. + + +--echo ############################################################## +--echo ### Initial block with some transactions + +--echo ### Slave: Make sure replication is not using GTID +--connection slave +--let $value= query_get_value(SHOW SLAVE STATUS, "Using_Gtid", 1) +--echo # Using_Gtid=$value + +--echo ### Master: Create and populate t1 +--connection master +CREATE TABLE t1(a TEXT) ENGINE=InnoDB; +START TRANSACTION; +INSERT INTO t1 VALUES ('tr#00:stmt#00 - slave run#0, before backup'); +INSERT INTO t1 VALUES ('tr#00:stmt#01 - slave run#0, before backup'); +INSERT INTO t1 VALUES ('tr#00:stmt#02 - slave run#0, before backup'); +COMMIT; +--sync_slave_with_master + + + +--echo ############################################################## +--echo ### Run the last transaction before mariadb-backup --backup +--echo ### Remember SHOW MASTER STATUS and @@gtid_binlog_pos +--echo ### before and after the transaction. + +--echo ### Master: Rember MASTER STATUS and @@gtid_binlog_pos before tr#01 +--connection master +--let $master_before_tr01_show_master_status_file=query_get_value(SHOW MASTER STATUS, File, 1) +--let $master_before_tr01_show_master_status_position=query_get_value(SHOW MASTER STATUS, Position, 1) +--let $master_before_tr01_gtid_binlog_pos=`SELECT @@global.gtid_binlog_pos` + +--echo ### Slave: Remember MASTER STATUS and @@gtid_binlog_pos before tr#01 +--connection slave +--let $slave_before_tr01_show_master_status_file=query_get_value(SHOW MASTER STATUS, File, 1) +--let $slave_before_tr01_show_master_status_position=query_get_value(SHOW MASTER STATUS, Position, 1) +--let $slave_before_tr01_gtid_binlog_pos=`SELECT @@global.gtid_binlog_pos` + +--echo ### Master: Run the actual last transaction before the backup +--connection master +START TRANSACTION; +INSERT INTO t1 VALUES ('tr#01:stmt#00 - slave run#0, before backup'); +INSERT INTO t1 VALUES ('tr#01:stmt#01 - slave run#0, before backup'); +INSERT INTO t1 VALUES ('tr#01:stmt#02 - slave run#0, before backup'); +COMMIT; +--sync_slave_with_master + +--echo ### Master: Remember MASTER STATUS and @@gtid_binlog_pos after tr#01 +--connection master +--let $master_after_tr01_show_master_status_file=query_get_value(SHOW MASTER STATUS, File, 1) +--let $master_after_tr01_show_master_status_position=query_get_value(SHOW MASTER STATUS, Position, 1) +--let $master_after_tr01_gtid_binlog_pos=`SELECT @@global.gtid_binlog_pos` + +--echo ### Slave: Remember MASTER STATUS and @@gtid_binlog_pos after tr#01 +--connection slave +--let $slave_after_tr01_show_master_status_file=query_get_value(SHOW MASTER STATUS, File, 1) +--let $slave_after_tr01_show_master_status_position=query_get_value(SHOW MASTER STATUS, Position, 1) +--let $slave_after_tr01_gtid_binlog_pos=`SELECT @@global.gtid_binlog_pos` + + +--echo ############################################################## +--echo ### Running `mariadb-backup --backup,--prepare` and checking +--echo ### that xtrabackup_slave_info and xtrabackup_binlog_info are OK + +--echo ### Slave: Create a backup +--let $backup_slave=$MYSQLTEST_VARDIR/tmp/backup-slave +--disable_result_log +--exec $XTRABACKUP $XTRABACKUP_BACKUP_OPTIONS --slave-info --backup --target-dir=$backup_slave +--enable_result_log + +--echo ### Slave: Prepare the backup +--exec $XTRABACKUP --prepare --target-dir=$backup_slave + +--echo ### Slave: xtrabackup files: +--echo ############################ xtrabackup_slave_info +--replace_result $master_after_tr01_show_master_status_file master_after_tr01_show_master_status_file $master_after_tr01_show_master_status_position master_after_tr01_show_master_status_position +--cat_file $backup_slave/xtrabackup_slave_info +--echo ############################ xtrabackup_binlog_info +--replace_result $slave_after_tr01_show_master_status_file slave_after_tr01_show_master_status_file $slave_after_tr01_show_master_status_position slave_after_tr01_show_master_status_position $slave_after_tr01_gtid_binlog_pos slave_after_tr01_gtid_binlog_pos +--cat_file $backup_slave/xtrabackup_binlog_info +--echo ############################ + + +--echo ############################################################## +--echo ### Run more transactions after the backup: +--echo ### - while the slave is still running, then +--echo ### - while the slave is shut down + +--echo ### Master: Run another transaction while the slave is still running +--connection master +START TRANSACTION; +INSERT INTO t1 VALUES ('tr#02:stmt#00 - slave run#0, after backup'); +INSERT INTO t1 VALUES ('tr#02:stmt#01 - slave run#0, after backup'); +INSERT INTO t1 VALUES ('tr#02:stmt@02 - slave run#0, after backup'); +COMMIT; +--sync_slave_with_master + +--echo ### Master: Remember MASTER STATUS and @@gtid_binlog_pos after tr#02 +--connection master +--let $master_after_tr02_show_master_status_file=query_get_value(SHOW MASTER STATUS, File, 1) +--let $master_after_tr02_show_master_status_position=query_get_value(SHOW MASTER STATUS, Position, 1) +--let $master_after_tr02_gtid_binlog_pos=`SELECT @@global.gtid_binlog_pos` + +--echo ### Slave: Remember MASTER STATUS and @@gtid_binlog_pos after tr#02 +--connection slave +--let $slave_after_tr02_show_master_status_file=query_get_value(SHOW MASTER STATUS, File, 1) +--let $slave_after_tr02_show_master_status_position=query_get_value(SHOW MASTER STATUS, Position, 1) +--let $slave_after_tr02_gtid_binlog_pos=`SELECT @@global.gtid_binlog_pos` + + +--echo ### Master: Checking SHOW BINLOG EVENTS + +--connection master +--vertical_results +### The BEGIN event +--replace_column 4 # 5 # +--replace_result $master_after_tr01_show_master_status_file master_after_tr01_show_master_status_file $master_after_tr01_show_master_status_position master_after_tr01_show_master_status_position $master_after_tr02_gtid_binlog_pos master_after_tr02_gtid_binlog_pos +--eval SHOW BINLOG EVENTS IN '$master_after_tr01_show_master_status_file' FROM $master_after_tr01_show_master_status_position LIMIT 0,1 +### The INSERT event +--replace_column 2 # 4 # 5 # +--replace_result $master_after_tr01_show_master_status_file master_after_tr01_show_master_status_file $master_after_tr01_show_master_status_position master_after_tr01_show_master_status_position +# Hide the difference between row and stmt binary logging +--replace_regex /use `test`; // /(Query|Annotate_rows)/Query_or_Annotate_rows/ +--eval SHOW BINLOG EVENTS IN '$master_after_tr01_show_master_status_file' FROM $master_after_tr01_show_master_status_position LIMIT 1,1 +--horizontal_results + +--echo ### Slave: Checking SHOW BINLOG EVENTS +--connection slave +--vertical_results +### The BEGIN event +--replace_column 2 # 5 # +--replace_result $slave_after_tr01_show_master_status_file slave_after_tr01_show_master_status_file $slave_after_tr01_show_master_status_position slave_after_tr01_show_master_status_position $slave_after_tr02_gtid_binlog_pos slave_after_tr02_gtid_binlog_pos +--eval SHOW BINLOG EVENTS IN '$slave_after_tr01_show_master_status_file' FROM $slave_after_tr01_show_master_status_position LIMIT 0,1 +### The INSERT event +--replace_column 2 # 4 # 5 # +--replace_result $slave_after_tr01_show_master_status_file slave_after_tr01_show_master_status_file $slave_after_tr01_show_master_status_position slave_after_tr01_show_master_status_position $slave_after_tr02_gtid_binlog_pos slave_after_tr02_gtid_binlog_pos +# Hide the difference between row and stmt binary logging +--replace_regex /use `test`; // /(Query|Annotate_rows)/Query_or_Annotate_rows/ +--eval SHOW BINLOG EVENTS IN '$slave_after_tr01_show_master_status_file' FROM $slave_after_tr01_show_master_status_position LIMIT 1,1 +--horizontal_results + +--echo ### Slave: Stop replication +--connection slave +STOP SLAVE; +--source include/wait_for_slave_to_stop.inc +RESET SLAVE; + +--echo ### Slave: Shutdown the server + +if ($cnf == "mariadb_to_mariadb") +{ + --let $rpl_server_number= 2 + --source include/rpl_stop_server.inc +} + +if ($cnf == "galera2_to_mariadb") +{ + --connection slave + --source $MYSQL_TEST_DIR/include/shutdown_mysqld.inc +} + +--echo ### Master: Run a transaction while the slave is shut down +--connection master +START TRANSACTION; +INSERT INTO t1 VALUES ('tr#03:stmt#00 - after slave run#0, slave is shut down, after backup'); +INSERT INTO t1 VALUES ('tr#03:stmt#01 - after slave run#0, slave is shut down, after backup'); +INSERT INTO t1 VALUES ('tr#03:stmt#02 - after slave run#0, slave is shut down, after backup'); +COMMIT; + + +--echo ############################################################## +--echo ### Emulate starting a new virgin slave + +--echo ### Slave: Remove the data directory +--rmdir $MYSQLD_DATADIR_SLAVE + +--echo ### Slave: Copy back the backup +--exec $XTRABACKUP $XTRABACKUP_COPY_BACK_OPTIONS --copy-back --datadir=$MYSQLD_DATADIR_SLAVE --target-dir=$backup_slave + +--echo ### Slave: Restart the server +if ($cnf == "mariadb_to_mariadb") +{ + --let $rpl_server_number= 2 + --source include/rpl_start_server.inc + --source include/wait_until_connected_again.inc +} + +if ($cnf == "galera2_to_mariadb") +{ + --connection slave + --source $MYSQL_TEST_DIR/include/start_mysqld.inc +} + +--echo ### Slave: Display the restored data before START SLAVE +--connection slave +SELECT * FROM t1 ORDER BY a; + +--echo ### Slave: Execute the CHANGE MASTER statement to set up the host and port +--replace_result $MASTER_MYPORT ### +--eval CHANGE MASTER '' TO MASTER_USER='root', MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_CONNECT_RETRY=1 + +--echo ### Slave: Execute the CHANGE MASTER statement from xtrabackup_slave_info +--replace_result $master_after_tr01_show_master_status_file master_after_tr01_show_master_status_file $master_after_tr01_show_master_status_position master_after_tr01_show_master_status_position +--source $backup_slave/xtrabackup_slave_info + +--echo ### Slave: Execute START SLAVE +--source include/start_slave.inc + +--echo ### Master: Wait for the slave to apply all master events +--connection master +--sync_slave_with_master slave + +--echo ### Slave: Make sure replication is not using GTID after the slave restart +--connection slave +--let $value= query_get_value(SHOW SLAVE STATUS, "Using_Gtid", 1) +--echo # Using_Gtid=$value + +--echo ### Slave: Display the restored data after START SLAVE +--connection slave +SELECT * FROM t1 ORDER BY a; + + +--echo ############################################################## +--echo ### Continue master transactions, check the new slave replicates well. + +--echo ### Master: Run a transaction after restarting replication +--connection master +START TRANSACTION; +INSERT INTO t1 VALUES ('tr#04:stmt#00 - slave run#1'); +INSERT INTO t1 VALUES ('tr#04:stmt#01 - slave run#1'); +INSERT INTO t1 VALUES ('tr#04:stmt#02 - slave run#1'); +COMMIT; +--sync_slave_with_master + +--echo ### Slave: Display the restored data + new transactions +--connection slave +SELECT * FROM t1 ORDER BY a; + + +--echo ############################################################## +--echo ### Cleanup + +--echo ### Removing the backup directory +--rmdir $backup_slave + +--connection master +DROP TABLE t1; +--sync_slave_with_master + +if ($cnf == "mariadb_to_mariadb") +{ + --source include/rpl_end.inc +} + +if ($cnf == "galera2_to_mariadb") +{ + STOP SLAVE; + --source include/wait_for_slave_to_stop.inc + RESET SLAVE ALL; + + --connection master + set global wsrep_on=OFF; + RESET MASTER; + set global wsrep_on=ON; +} diff --git a/mysql-test/lib/mtr_report.pm b/mysql-test/lib/mtr_report.pm index 97c48c19112..0c3c45f3b18 100644 --- a/mysql-test/lib/mtr_report.pm +++ b/mysql-test/lib/mtr_report.pm @@ -87,12 +87,16 @@ sub flush_out { $out_line = ""; } +use if $^O eq "MSWin32", "threads::shared"; +my $flush_lock :shared; + # Print to stdout sub print_out { if(IS_WIN32PERL) { $out_line .= $_[0]; # Flush buffered output on new lines. if (rindex($_[0], "\n") != -1) { + lock($flush_lock); flush_out(); } } else { diff --git a/mysql-test/main/column_compression_parts.result b/mysql-test/main/column_compression_parts.result index fa12217ce22..5f5539b723c 100644 --- a/mysql-test/main/column_compression_parts.result +++ b/mysql-test/main/column_compression_parts.result @@ -12,7 +12,6 @@ INSERT INTO t1 VALUES (1,REPEAT('a',100)),(2,REPEAT('v',200)),(3,REPEAT('r',300) INSERT INTO t1 VALUES (5,REPEAT('k',500)),(6,'April'),(7,7),(8,""),(9,"M"),(10,DEFAULT); ALTER TABLE t1 ANALYZE PARTITION p1; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK ALTER TABLE t1 CHECK PARTITION p2; Table Op Msg_type Msg_text diff --git a/mysql-test/main/derived_view.result b/mysql-test/main/derived_view.result index 130516cc950..3cd38a62d92 100644 --- a/mysql-test/main/derived_view.result +++ b/mysql-test/main/derived_view.result @@ -4354,6 +4354,40 @@ a drop table t1, t2; drop view v1; drop procedure aproc; +# +# MDEV-31305: Aggregation over materialized derived table +# +CREATE VIEW v AS +SELECT seq1.seq AS dim1, seq2.seq AS dim2, seq3.seq AS dim3, +FLOOR(RAND(13) * 5) AS p +FROM seq_100_to_105 seq1 +JOIN seq_10_to_15 seq2 +JOIN seq_1_to_5 seq3; +SELECT v.*, SUM(p) from v; +dim1 dim2 dim3 p SUM(p) +100 10 1 2 371 +SELECT d.*, SUM(p) +FROM ( +SELECT seq1.seq AS dim1, seq2.seq AS dim2, seq3.seq AS dim3, +FLOOR(RAND(13) * 5) AS p +FROM seq_100_to_105 seq1 +JOIN seq_10_to_15 seq2 +JOIN seq_1_to_5 seq3 +) d; +dim1 dim2 dim3 p SUM(p) +100 10 1 2 371 +WITH demo AS +( +SELECT seq1.seq AS dim1, seq2.seq AS dim2, seq3.seq AS dim3, +FLOOR(RAND(13) * 5) AS p +FROM seq_100_to_105 seq1 +JOIN seq_10_to_15 seq2 +JOIN seq_1_to_5 seq3 +) +SELECT d.*, SUM(p) FROM demo d; +dim1 dim2 dim3 p SUM(p) +100 10 1 2 371 +DROP VIEW v; # End of 10.4 tests # # MDEV-31143: view with ORDER BY used in query with rownum() in WHERE diff --git a/mysql-test/main/derived_view.test b/mysql-test/main/derived_view.test index a7b09e7b02c..b7c9c91480a 100644 --- a/mysql-test/main/derived_view.test +++ b/mysql-test/main/derived_view.test @@ -2803,6 +2803,42 @@ drop table t1, t2; drop view v1; drop procedure aproc; +--echo # +--echo # MDEV-31305: Aggregation over materialized derived table +--echo # + +--source include/have_sequence.inc + +CREATE VIEW v AS + SELECT seq1.seq AS dim1, seq2.seq AS dim2, seq3.seq AS dim3, + FLOOR(RAND(13) * 5) AS p + FROM seq_100_to_105 seq1 + JOIN seq_10_to_15 seq2 + JOIN seq_1_to_5 seq3; + +SELECT v.*, SUM(p) from v; + +SELECT d.*, SUM(p) + FROM ( + SELECT seq1.seq AS dim1, seq2.seq AS dim2, seq3.seq AS dim3, + FLOOR(RAND(13) * 5) AS p + FROM seq_100_to_105 seq1 + JOIN seq_10_to_15 seq2 + JOIN seq_1_to_5 seq3 +) d; + +WITH demo AS +( + SELECT seq1.seq AS dim1, seq2.seq AS dim2, seq3.seq AS dim3, + FLOOR(RAND(13) * 5) AS p + FROM seq_100_to_105 seq1 + JOIN seq_10_to_15 seq2 + JOIN seq_1_to_5 seq3 +) +SELECT d.*, SUM(p) FROM demo d; + +DROP VIEW v; + --echo # End of 10.4 tests --echo # diff --git a/mysql-test/main/distinct_notembedded.result b/mysql-test/main/distinct_notembedded.result new file mode 100644 index 00000000000..df81fe1c228 --- /dev/null +++ b/mysql-test/main/distinct_notembedded.result @@ -0,0 +1,322 @@ +# +# MDEV-30660 COUNT DISTINCT seems unnecessarily slow when run on a PK +# +set @save_optimizer_trace = @@optimizer_trace; +SET optimizer_trace='enabled=on'; +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT NOT NULL); +INSERT INTO t1 VALUES (1,1), (2,1), (3,1); +# Optimization is applied (aggregator=simple): +SELECT COUNT(DISTINCT a) FROM t1; +COUNT(DISTINCT a) +3 +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "count(distinct t1.a)", + "aggregator_type": "simple" + } +] +SELECT AVG(DISTINCT a), SUM(DISTINCT b) FROM t1; +AVG(DISTINCT a) SUM(DISTINCT b) +2.0000 1 +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "avg(distinct t1.a)", + "aggregator_type": "simple" + }, + { + "function": "sum(distinct t1.b)", + "aggregator_type": "distinct" + } +] +# Only `a` is unique but it's enough to eliminate DISTINCT: +SELECT COUNT(DISTINCT b, a) FROM t1; +COUNT(DISTINCT b, a) +3 +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "count(distinct t1.b,t1.a)", + "aggregator_type": "simple" + } +] +SELECT COUNT(DISTINCT a, a + b) FROM t1; +COUNT(DISTINCT a, a + b) +3 +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "count(distinct t1.a,t1.a + t1.b)", + "aggregator_type": "simple" + } +] +SELECT SUM(DISTINCT a), AVG(DISTINCT a), COUNT(DISTINCT a) FROM t1 WHERE a > 1; +SUM(DISTINCT a) AVG(DISTINCT a) COUNT(DISTINCT a) +5 2.5000 2 +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "sum(distinct t1.a)", + "aggregator_type": "simple" + }, + { + "function": "avg(distinct t1.a)", + "aggregator_type": "simple" + }, + { + "function": "count(distinct t1.a)", + "aggregator_type": "simple" + } +] +# Optimization is not applied 'cause function argument is not a field +# (aggregator=distinct): +SELECT SUM(DISTINCT a + b) FROM t1; +SUM(DISTINCT a + b) +9 +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "sum(distinct t1.a + t1.b)", + "aggregator_type": "distinct" + } +] +SELECT COUNT(DISTINCT b) FROM t1; +COUNT(DISTINCT b) +1 +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "count(distinct t1.b)", + "aggregator_type": "distinct" + } +] +SELECT AVG(DISTINCT b / a) FROM t1; +AVG(DISTINCT b / a) +0.61110000 +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "avg(distinct t1.b / t1.a)", + "aggregator_type": "distinct" + } +] +EXPLAIN SELECT COUNT(DISTINCT (SELECT a)) FROM t1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 index NULL PRIMARY 4 NULL 3 Using index +2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "count(distinct (/* select#2 */ select t1.a))", + "aggregator_type": "distinct" + } +] +CREATE TABLE t2 (a INT); +INSERT INTO t2 VALUES (1), (2); +# Optimization is not applied 'cause there is more than one table +SELECT COUNT(DISTINCT t1.a) FROM t1, t2; +COUNT(DISTINCT t1.a) +3 +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "count(distinct t1.a)", + "aggregator_type": "distinct" + } +] +SELECT AVG(DISTINCT t1.a) FROM t1, t2; +AVG(DISTINCT t1.a) +2.0000 +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "avg(distinct t1.a)", + "aggregator_type": "distinct" + } +] +# Const tables, optimization is applied +SELECT COUNT(DISTINCT a) FROM t1, (SELECT 1) AS t2; +COUNT(DISTINCT a) +3 +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "count(distinct t1.a)", + "aggregator_type": "simple" + } +] +SELECT AVG(DISTINCT t1.a) FROM (SELECT 1 AS a) AS t2, t1, (SELECT 2 AS a) AS t3; +AVG(DISTINCT t1.a) +2.0000 +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "avg(distinct t1.a)", + "aggregator_type": "simple" + } +] +SELECT COUNT(DISTINCT a) FROM t1, (SELECT 1 UNION SELECT 2) AS t2; +COUNT(DISTINCT a) +3 +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "count(distinct t1.a)", + "aggregator_type": "distinct" + } +] +# Unique index on two columns +CREATE TABLE t3 (a INT NOT NULL, b INT NOT NULL); +INSERT INTO t3 VALUES (1,1), (1,2), (1,3), (2,1), (2,2), (3,1), (3,2); +CREATE UNIQUE INDEX t3_a_b ON t3 (a, b); +# Optimization is applied: +SELECT COUNT(DISTINCT a, b) FROM t3; +COUNT(DISTINCT a, b) +7 +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "count(distinct t3.a,t3.b)", + "aggregator_type": "simple" + } +] +SELECT COUNT(DISTINCT b, a) FROM t3; +COUNT(DISTINCT b, a) +7 +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "count(distinct t3.b,t3.a)", + "aggregator_type": "simple" + } +] +SELECT COUNT(DISTINCT b, a) FROM t3 WHERE a < 3; +COUNT(DISTINCT b, a) +5 +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "count(distinct t3.b,t3.a)", + "aggregator_type": "simple" + } +] +# Optimization is applied to one of the functions: +SELECT COUNT(DISTINCT b), SUM(DISTINCT a), SUM(DISTINCT a + b) FROM t3 GROUP BY a; +COUNT(DISTINCT b) SUM(DISTINCT a) SUM(DISTINCT a + b) +3 1 9 +2 2 7 +2 3 9 +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "count(distinct t3.b)", + "aggregator_type": "simple" + }, + { + "function": "sum(distinct t3.a)", + "aggregator_type": "distinct" + }, + { + "function": "sum(distinct t3.a + t3.b)", + "aggregator_type": "distinct" + } +] +# Can't apply optimization 'cause GROUP BY argument is not a field: +SELECT COUNT(DISTINCT b) FROM t3 GROUP BY a+b; +COUNT(DISTINCT b) +1 +2 +3 +1 +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "count(distinct t3.b)", + "aggregator_type": "distinct" + } +] +# Test merged view +CREATE VIEW v1 AS SELECT * FROM t1; +# Optimization is applied +SELECT COUNT(DISTINCT a, b) FROM v1; +COUNT(DISTINCT a, b) +3 +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "count(distinct t1.a,t1.b)", + "aggregator_type": "simple" + } +] +# GROUP_CONCAT implements non-standard distinct aggregator +SELECT GROUP_CONCAT(b) FROM t1; +GROUP_CONCAT(b) +1,1,1 +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "group_concat(t1.b separator ',')", + "aggregator_type": "simple" + } +] +SELECT GROUP_CONCAT(DISTINCT b) FROM t1; +GROUP_CONCAT(DISTINCT b) +1 +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '$**.prepare_sum_aggregators')) AS JS +FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JS +[ + { + "function": "group_concat(distinct t1.b separator ',')", + "aggregator_type": "distinct" + } +] +DROP TABLE t1, t2, t3; +DROP VIEW v1; +SET optimizer_trace = @save_optimizer_trace; +# +# end of 10.5 tests +# diff --git a/mysql-test/main/distinct_notembedded.test b/mysql-test/main/distinct_notembedded.test new file mode 100644 index 00000000000..9ef2f45913c --- /dev/null +++ b/mysql-test/main/distinct_notembedded.test @@ -0,0 +1,109 @@ +# Embedded doesn't have optimizer trace: +--source include/not_embedded.inc +--source include/have_sequence.inc + +--echo # +--echo # MDEV-30660 COUNT DISTINCT seems unnecessarily slow when run on a PK +--echo # + +set @save_optimizer_trace = @@optimizer_trace; +SET optimizer_trace='enabled=on'; +let $trace= +SELECT JSON_DETAILED(JSON_EXTRACT(trace, '\$**.prepare_sum_aggregators')) AS JS + FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; + +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT NOT NULL); +INSERT INTO t1 VALUES (1,1), (2,1), (3,1); + +--echo # Optimization is applied (aggregator=simple): +SELECT COUNT(DISTINCT a) FROM t1; +eval $trace; + +SELECT AVG(DISTINCT a), SUM(DISTINCT b) FROM t1; +eval $trace; + +--echo # Only `a` is unique but it's enough to eliminate DISTINCT: +SELECT COUNT(DISTINCT b, a) FROM t1; +eval $trace; + +SELECT COUNT(DISTINCT a, a + b) FROM t1; +eval $trace; + +SELECT SUM(DISTINCT a), AVG(DISTINCT a), COUNT(DISTINCT a) FROM t1 WHERE a > 1; +eval $trace; + +--echo # Optimization is not applied 'cause function argument is not a field +--echo # (aggregator=distinct): +SELECT SUM(DISTINCT a + b) FROM t1; +eval $trace; + +SELECT COUNT(DISTINCT b) FROM t1; +eval $trace; + +SELECT AVG(DISTINCT b / a) FROM t1; +eval $trace; + +EXPLAIN SELECT COUNT(DISTINCT (SELECT a)) FROM t1; +eval $trace; + +CREATE TABLE t2 (a INT); +INSERT INTO t2 VALUES (1), (2); + +--echo # Optimization is not applied 'cause there is more than one table +SELECT COUNT(DISTINCT t1.a) FROM t1, t2; +eval $trace; + +SELECT AVG(DISTINCT t1.a) FROM t1, t2; +eval $trace; + +--echo # Const tables, optimization is applied +SELECT COUNT(DISTINCT a) FROM t1, (SELECT 1) AS t2; +eval $trace; + +SELECT AVG(DISTINCT t1.a) FROM (SELECT 1 AS a) AS t2, t1, (SELECT 2 AS a) AS t3; +eval $trace; + +SELECT COUNT(DISTINCT a) FROM t1, (SELECT 1 UNION SELECT 2) AS t2; +eval $trace; + +--echo # Unique index on two columns +CREATE TABLE t3 (a INT NOT NULL, b INT NOT NULL); +INSERT INTO t3 VALUES (1,1), (1,2), (1,3), (2,1), (2,2), (3,1), (3,2); +CREATE UNIQUE INDEX t3_a_b ON t3 (a, b); +--echo # Optimization is applied: +SELECT COUNT(DISTINCT a, b) FROM t3; +eval $trace; + +SELECT COUNT(DISTINCT b, a) FROM t3; +eval $trace; + +SELECT COUNT(DISTINCT b, a) FROM t3 WHERE a < 3; +eval $trace; + +--echo # Optimization is applied to one of the functions: +SELECT COUNT(DISTINCT b), SUM(DISTINCT a), SUM(DISTINCT a + b) FROM t3 GROUP BY a; +eval $trace; + +--echo # Can't apply optimization 'cause GROUP BY argument is not a field: +SELECT COUNT(DISTINCT b) FROM t3 GROUP BY a+b; +eval $trace; + +--echo # Test merged view +CREATE VIEW v1 AS SELECT * FROM t1; +--echo # Optimization is applied +SELECT COUNT(DISTINCT a, b) FROM v1; +eval $trace; + +--echo # GROUP_CONCAT implements non-standard distinct aggregator +SELECT GROUP_CONCAT(b) FROM t1; +eval $trace; + +SELECT GROUP_CONCAT(DISTINCT b) FROM t1; +eval $trace; + +DROP TABLE t1, t2, t3; +DROP VIEW v1; +SET optimizer_trace = @save_optimizer_trace; +--echo # +--echo # end of 10.5 tests +--echo # diff --git a/mysql-test/main/func_str.result b/mysql-test/main/func_str.result index df7b7cd52ce..a54089e46f6 100644 --- a/mysql-test/main/func_str.result +++ b/mysql-test/main/func_str.result @@ -5487,3 +5487,37 @@ Warning 1292 Truncated incorrect BINARY(2) value: '...random bytes...' # # End of 10.10 tests # +# +# Start of 10.11 tests +# +# +# MDEV-33392 Server crashes when using RANDOM_BYTES function and GROUP BY clause on a column with a negative value +# +SET sql_mode=''; +CREATE TABLE t1 (a VARCHAR(255)) ENGINE=MyISAM; +INSERT INTO t1 VALUES (9494),(9495),(9496),(9497),(9498),(9499),(9500),(9501),(9502),(9503); +SELECT RANDOM_BYTES (-1) f1,a f2 FROM t1 GROUP BY f1,f2; +f1 f2 +NULL 9494 +NULL 9495 +NULL 9496 +NULL 9497 +NULL 9498 +NULL 9499 +NULL 9500 +NULL 9501 +NULL 9502 +NULL 9503 +CREATE TABLE t2 AS SELECT RANDOM_BYTES (-1) f1,a f2 FROM t1 GROUP BY f1,f2; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` binary(0) DEFAULT NULL, + `f2` varchar(255) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +DROP TABLE t2; +DROP TABLE t1; +SET sql_mode=DEFAULT; +# +# End of 10.11 tests +# diff --git a/mysql-test/main/func_str.test b/mysql-test/main/func_str.test index e939b21e60a..b34623d96a7 100644 --- a/mysql-test/main/func_str.test +++ b/mysql-test/main/func_str.test @@ -2457,3 +2457,25 @@ select "a" in ("abc", (convert(random_bytes(8) ,binary(2)))); --echo # --echo # End of 10.10 tests --echo # + +--echo # +--echo # Start of 10.11 tests +--echo # + +--echo # +--echo # MDEV-33392 Server crashes when using RANDOM_BYTES function and GROUP BY clause on a column with a negative value +--echo # + +SET sql_mode=''; +CREATE TABLE t1 (a VARCHAR(255)) ENGINE=MyISAM; +INSERT INTO t1 VALUES (9494),(9495),(9496),(9497),(9498),(9499),(9500),(9501),(9502),(9503); +SELECT RANDOM_BYTES (-1) f1,a f2 FROM t1 GROUP BY f1,f2; +CREATE TABLE t2 AS SELECT RANDOM_BYTES (-1) f1,a f2 FROM t1 GROUP BY f1,f2; +SHOW CREATE TABLE t2; +DROP TABLE t2; +DROP TABLE t1; +SET sql_mode=DEFAULT; + +--echo # +--echo # End of 10.11 tests +--echo # diff --git a/mysql-test/main/innodb_ext_key.test b/mysql-test/main/innodb_ext_key.test index 49112c10c57..c5ef5d6f63b 100644 --- a/mysql-test/main/innodb_ext_key.test +++ b/mysql-test/main/innodb_ext_key.test @@ -6,6 +6,8 @@ --source include/no_valgrind_without_big.inc --source include/have_sequence.inc +--source include/innodb_stable_estimates.inc + SET SESSION DEFAULT_STORAGE_ENGINE='InnoDB'; set @innodb_stats_persistent_save= @@innodb_stats_persistent; diff --git a/mysql-test/main/lowercase_table2.result b/mysql-test/main/lowercase_table2.result old mode 100755 new mode 100644 diff --git a/mysql-test/main/mysql_connector_net.test b/mysql-test/main/mysql_connector_net.test index c1dce65adc8..ad048c20b3d 100644 --- a/mysql-test/main/mysql_connector_net.test +++ b/mysql-test/main/mysql_connector_net.test @@ -4,7 +4,7 @@ let $sys_errno=0; # Error 100 is returned by the powershell script # if MySql.Data is not installed --error 0,100 ---exec powershell -NoLogo -NoProfile -File main\mysql_connector_net.ps1 +--exec powershell -ExecutionPolicy Bypass -NoLogo -NoProfile -File main\mysql_connector_net.ps1 if ($sys_errno != 0) { --skip Connector/NET is not installed diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result index b7fbc74a51b..65a6ab97178 100644 --- a/mysql-test/main/opt_trace.result +++ b/mysql-test/main/opt_trace.result @@ -1790,6 +1790,12 @@ set statement optimizer_scan_setup_cost=0 for EXPLAIN SELECT MIN(d) FROM t1 wher } } ] + }, + { + "prepare_sum_aggregators": { + "function": "min(t1.d)", + "aggregator_type": "simple" + } } ] } @@ -2010,6 +2016,18 @@ EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id { }, { "test_if_skip_sort_order": [] + }, + { + "prepare_sum_aggregators": { + "function": "min(t1.a)", + "aggregator_type": "simple" + } + }, + { + "prepare_sum_aggregators": { + "function": "max(t1.a)", + "aggregator_type": "simple" + } } ] } @@ -12238,6 +12256,25 @@ JS drop table t1,t2,t3,t10,t11; set optimizer_trace=DEFAULT; # +# MDEV-29179 Condition pushdown from HAVING into WHERE is not shown in optimizer trace +# +CREATE TABLE t1 (a INT, b VARCHAR(1), KEY (a), KEY(b,a)) ENGINE=MEMORY; +INSERT INTO t1 VALUES (4,'n'),(1,'h'),(NULL,'w'); +SET optimizer_trace= 'enabled=on'; +SELECT b, a FROM t1 WHERE b <> 'p' OR a = 4 GROUP BY b, a HAVING a <= 7; +b a +h 1 +n 4 +SELECT json_detailed(json_extract(trace, '$**.steps[*].join_optimization.steps[*].condition_pushdown_from_having') ) exp1, JSON_VALID(trace) exp2 FROM information_schema.optimizer_trace; +exp1 exp2 +[ + { + "conds": "(t1.b <> 'p' or multiple equal(4, t1.a)) and t1.a <= 7", + "having": null + } +] 1 +DROP TABLE t1; +# # End of 10.4 tests # set optimizer_trace='enabled=on'; diff --git a/mysql-test/main/opt_trace.test b/mysql-test/main/opt_trace.test index f69a200f629..b3a9c211ead 100644 --- a/mysql-test/main/opt_trace.test +++ b/mysql-test/main/opt_trace.test @@ -775,6 +775,16 @@ from information_schema.optimizer_trace; drop table t1,t2,t3,t10,t11; set optimizer_trace=DEFAULT; +--echo # +--echo # MDEV-29179 Condition pushdown from HAVING into WHERE is not shown in optimizer trace +--echo # + +CREATE TABLE t1 (a INT, b VARCHAR(1), KEY (a), KEY(b,a)) ENGINE=MEMORY; +INSERT INTO t1 VALUES (4,'n'),(1,'h'),(NULL,'w'); +SET optimizer_trace= 'enabled=on'; +SELECT b, a FROM t1 WHERE b <> 'p' OR a = 4 GROUP BY b, a HAVING a <= 7; SELECT json_detailed(json_extract(trace, '$**.steps[*].join_optimization.steps[*].condition_pushdown_from_having') ) exp1, JSON_VALID(trace) exp2 FROM information_schema.optimizer_trace; +DROP TABLE t1; + --echo # --echo # End of 10.4 tests --echo # diff --git a/mysql-test/main/partition.result b/mysql-test/main/partition.result index 3cb9b3043cd..68b74aaf1c4 100644 --- a/mysql-test/main/partition.result +++ b/mysql-test/main/partition.result @@ -2063,7 +2063,6 @@ ALTER TABLE t1 ANALYZE PARTITION p1 EXTENDED; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'EXTENDED' at line 1 ALTER TABLE t1 ANALYZE PARTITION p1; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK ALTER TABLE t1 CHECK PARTITION p1; Table Op Msg_type Msg_text diff --git a/mysql-test/main/partition_binlog.result b/mysql-test/main/partition_binlog.result index 45cd636c1f9..5ecccde4b91 100644 --- a/mysql-test/main/partition_binlog.result +++ b/mysql-test/main/partition_binlog.result @@ -27,7 +27,6 @@ Table Op Msg_type Msg_text test.t1 repair error Wrong partition name or partition list ALTER TABLE t1 ANALYZE PARTITION p0; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK ALTER TABLE t1 CHECK PARTITION p0; Table Op Msg_type Msg_text diff --git a/mysql-test/main/ps.result b/mysql-test/main/ps.result index 501a8b8c3d4..e24eb1e838b 100644 --- a/mysql-test/main/ps.result +++ b/mysql-test/main/ps.result @@ -5808,5 +5808,123 @@ GROUP_CONCAT(@x) 0 DROP TABLE t; # +# MDEV-15703: Crash in EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING DEFAULT +# +PREPARE stmt FROM 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)'; +EXECUTE stmt USING DEFAULT; +ERROR HY000: Default/ignore value is not supported for such parameter usage +DEALLOCATE PREPARE stmt; +PREPARE stmt FROM 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)'; +EXECUTE stmt USING IGNORE; +ERROR HY000: Default/ignore value is not supported for such parameter usage +DEALLOCATE PREPARE stmt; +EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING DEFAULT; +ERROR HY000: Default/ignore value is not supported for such parameter usage +EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING IGNORE; +ERROR HY000: Default/ignore value is not supported for such parameter usage +EXECUTE IMMEDIATE 'BEGIN NOT ATOMIC DECLARE a INT DEFAULT ?; END' USING DEFAULT; +ERROR HY000: Default/ignore value is not supported for such parameter usage +EXECUTE IMMEDIATE 'BEGIN NOT ATOMIC DECLARE a INT DEFAULT ?; END' USING IGNORE; +ERROR HY000: Default/ignore value is not supported for such parameter usage +CREATE PROCEDURE p1(a INT) SELECT 1; +EXECUTE IMMEDIATE 'CALL p1(?)' USING DEFAULT; +ERROR HY000: Default/ignore value is not supported for such parameter usage +EXECUTE IMMEDIATE 'CALL p1(?)' USING IGNORE; +ERROR HY000: Default/ignore value is not supported for such parameter usage +DROP PROCEDURE p1; +EXECUTE IMMEDIATE 'SELECT ? UNION SELECT 1' USING DEFAULT; +ERROR HY000: Default/ignore value is not supported for such parameter usage +EXECUTE IMMEDIATE 'SELECT ? UNION SELECT 1' USING IGNORE; +ERROR HY000: Default/ignore value is not supported for such parameter usage +EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION ALL SELECT 1) AS derived' USING DEFAULT; +ERROR HY000: Default/ignore value is not supported for such parameter usage +EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION ALL SELECT 1) AS derived' USING IGNORE; +ERROR HY000: Default/ignore value is not supported for such parameter usage +EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION DISTINCT SELECT 1) AS derived' USING DEFAULT; +ERROR HY000: Default/ignore value is not supported for such parameter usage +EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION DISTINCT SELECT 1) AS derived' USING IGNORE; +ERROR HY000: Default/ignore value is not supported for such parameter usage +# multi-update and DEFAULT +CREATE TABLE t1 (a INT, b INT DEFAULT a); +INSERT into t1 VALUES (1,2),(2,3); +CREATE TABLE t2 (a INT, b INT DEFAULT a); +INSERT INTO t2 VALUES (1,10),(2,30); +UPDATE t1,t2 SET t1.b = DEFAULT, t2.b = DEFAULT WHERE t1.a=t2.a; +SELECT * FROM t1; +a b +1 1 +2 2 +SELECT * FROM t2; +a b +1 1 +2 2 +# re-check the case for Prepared Statement with parameters +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +INSERT INTO t1 VALUES (1,2),(2,3); +INSERT INTO t2 VALUES (1,10),(2,30); +EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING DEFAULT, DEFAULT; +SELECT * FROM t1; +a b +1 1 +2 2 +SELECT * FROM t2; +a b +1 1 +2 2 +DROP TABLE t1, t2; +# multi-update and IGNORE +CREATE TABLE t1 (a INT, b INT default a); +INSERT INTO t1 VALUES (1,2),(2,3); +CREATE TABLE t2 (a INT, b INT default a); +INSERT INTO t2 VALUES (1,10),(2,30); +UPDATE t1,t2 SET t1.b = IGNORE, t2.b = IGNORE WHERE t1.a=t2.a; +SELECT * FROM t1; +a b +1 2 +2 3 +SELECT * FROM t2; +a b +1 NULL +2 NULL +# re-check the case for Prepared Statement with parameters +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +INSERT INTO t1 VALUES (1,2),(2,3); +INSERT INTO t2 VALUES (1,10),(2,30); +EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING IGNORE, IGNORE; +SELECT * FROM t1; +a b +1 2 +2 3 +SELECT * FROM t2; +a b +1 10 +2 30 +DROP TABLE t1, t2; +# multi-update and DEFAULT parameter (no default) +CREATE TABLE t1 (a INT, b INT NOT NULL); +INSERT INTO t1 VALUES (1,2),(2,3); +CREATE TABLE t2 (a INT, b INT NOT NULL); +INSERT INTO t2 VALUES (1,10),(2,30); +EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING DEFAULT, DEFAULT; +ERROR HY000: Field 'b' doesn't have a default value +DROP TABLE t1, t2; +# multi-update and IGNORE parameter (no default) +CREATE TABLE t1 (a INT, b INT NOT NULL); +INSERT INTO t1 VALUES (1,2),(2,3); +CREATE TABLE t2 (a INT, b INT NOT NULL); +INSERT INTO t2 VALUES (1,10),(2,30); +EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING IGNORE, IGNORE; +SELECT * FROM t1; +a b +1 2 +2 3 +SELECT * FROM t2; +a b +1 10 +2 30 +DROP TABLE t1, t2; +# # End of 10.4 tests # diff --git a/mysql-test/main/ps.test b/mysql-test/main/ps.test index 675c510286d..30df8dcec32 100644 --- a/mysql-test/main/ps.test +++ b/mysql-test/main/ps.test @@ -5248,6 +5248,125 @@ EXECUTE IMMEDIATE 'SELECT GROUP_CONCAT(@x) FROM t GROUP BY @x := f'; DROP TABLE t; +--echo # +--echo # MDEV-15703: Crash in EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING DEFAULT +--echo # + +PREPARE stmt FROM 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)'; +--error ER_INVALID_DEFAULT_PARAM +EXECUTE stmt USING DEFAULT; +DEALLOCATE PREPARE stmt; + +PREPARE stmt FROM 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)'; +--error ER_INVALID_DEFAULT_PARAM +EXECUTE stmt USING IGNORE; +DEALLOCATE PREPARE stmt; + +--error ER_INVALID_DEFAULT_PARAM +EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING DEFAULT; + +--error ER_INVALID_DEFAULT_PARAM +EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING IGNORE; + +--error ER_INVALID_DEFAULT_PARAM +EXECUTE IMMEDIATE 'BEGIN NOT ATOMIC DECLARE a INT DEFAULT ?; END' USING DEFAULT; + +--error ER_INVALID_DEFAULT_PARAM +EXECUTE IMMEDIATE 'BEGIN NOT ATOMIC DECLARE a INT DEFAULT ?; END' USING IGNORE; + +CREATE PROCEDURE p1(a INT) SELECT 1; +--error ER_INVALID_DEFAULT_PARAM +EXECUTE IMMEDIATE 'CALL p1(?)' USING DEFAULT; +--error ER_INVALID_DEFAULT_PARAM +EXECUTE IMMEDIATE 'CALL p1(?)' USING IGNORE; +DROP PROCEDURE p1; + +--error ER_INVALID_DEFAULT_PARAM +EXECUTE IMMEDIATE 'SELECT ? UNION SELECT 1' USING DEFAULT; +--error ER_INVALID_DEFAULT_PARAM +EXECUTE IMMEDIATE 'SELECT ? UNION SELECT 1' USING IGNORE; + +--error ER_INVALID_DEFAULT_PARAM +EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION ALL SELECT 1) AS derived' USING DEFAULT; +--error ER_INVALID_DEFAULT_PARAM +EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION ALL SELECT 1) AS derived' USING IGNORE; + +--error ER_INVALID_DEFAULT_PARAM +EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION DISTINCT SELECT 1) AS derived' USING DEFAULT; +--error ER_INVALID_DEFAULT_PARAM +EXECUTE IMMEDIATE 'SELECT * FROM (SELECT ? UNION DISTINCT SELECT 1) AS derived' USING IGNORE; + +--echo # multi-update and DEFAULT +CREATE TABLE t1 (a INT, b INT DEFAULT a); +INSERT into t1 VALUES (1,2),(2,3); +CREATE TABLE t2 (a INT, b INT DEFAULT a); +INSERT INTO t2 VALUES (1,10),(2,30); + +UPDATE t1,t2 SET t1.b = DEFAULT, t2.b = DEFAULT WHERE t1.a=t2.a; +SELECT * FROM t1; +SELECT * FROM t2; + +--echo # re-check the case for Prepared Statement with parameters +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +INSERT INTO t1 VALUES (1,2),(2,3); +INSERT INTO t2 VALUES (1,10),(2,30); + +EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING DEFAULT, DEFAULT; +SELECT * FROM t1; +SELECT * FROM t2; + +# Cleanup +DROP TABLE t1, t2; + +--echo # multi-update and IGNORE +CREATE TABLE t1 (a INT, b INT default a); +INSERT INTO t1 VALUES (1,2),(2,3); +CREATE TABLE t2 (a INT, b INT default a); +INSERT INTO t2 VALUES (1,10),(2,30); + +UPDATE t1,t2 SET t1.b = IGNORE, t2.b = IGNORE WHERE t1.a=t2.a; +SELECT * FROM t1; +SELECT * FROM t2; + +--echo # re-check the case for Prepared Statement with parameters +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +INSERT INTO t1 VALUES (1,2),(2,3); +INSERT INTO t2 VALUES (1,10),(2,30); + +EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING IGNORE, IGNORE; +SELECT * FROM t1; +SELECT * FROM t2; + +# Cleanup +DROP TABLE t1, t2; + +--echo # multi-update and DEFAULT parameter (no default) +CREATE TABLE t1 (a INT, b INT NOT NULL); +INSERT INTO t1 VALUES (1,2),(2,3); +CREATE TABLE t2 (a INT, b INT NOT NULL); +INSERT INTO t2 VALUES (1,10),(2,30); + +--error ER_NO_DEFAULT_FOR_FIELD +EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING DEFAULT, DEFAULT; + +# Cleanup +DROP TABLE t1, t2; + +--echo # multi-update and IGNORE parameter (no default) +CREATE TABLE t1 (a INT, b INT NOT NULL); +INSERT INTO t1 VALUES (1,2),(2,3); +CREATE TABLE t2 (a INT, b INT NOT NULL); +INSERT INTO t2 VALUES (1,10),(2,30); + +EXECUTE IMMEDIATE 'UPDATE t1,t2 SET t1.b = ?, t2.b = ? WHERE t1.a=t2.a' USING IGNORE, IGNORE; +SELECT * FROM t1; +SELECT * FROM t2; + +# Cleanup +DROP TABLE t1, t2; + --echo # --echo # End of 10.4 tests --echo # 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/main/selectivity_innodb_notembedded.result b/mysql-test/main/selectivity_innodb_notembedded.result index 8b06fe7556b..f2b7e9396ba 100644 --- a/mysql-test/main/selectivity_innodb_notembedded.result +++ b/mysql-test/main/selectivity_innodb_notembedded.result @@ -88,15 +88,151 @@ sel ] set optimizer_trace=@tmp; drop table t0,t1,t10; -set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; set histogram_size=@save_histogram_size; -set use_stat_tables= @save_use_stat_tables; # # End of 10.4 tests # # +# MDEV-33314: Crash inside calculate_cond_selectivity_for_table() with many columns +# +set optimizer_use_condition_selectivity= 4; +set use_stat_tables= preferably; +# +# create table t1 (col0 int, col1 int, col2 int, ...); +# +$create_tbl; +# +# insert into t1 select seq, ... seq from seq_1_to_10; +# +$insert_cmd; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +set @trace_tmp=@@optimizer_trace; +set optimizer_trace=1; +# +# Basic testcase: don't crash for many-column selectivity +# explain extended select * from t1 where col0>1 and col1>1 and col2>1 and ... +# +$query_tbl; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.0322836, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "ALL", + "loops": 1, + "rows": 100, + "cost": 0.0322836, + "filtered": 53.32928848, + "attached_condition": "t1.col0 > 1 and t1.col1 > 1 and t1.col2 > 1 and t1.col3 > 1 and t1.col4 > 1 and t1.col5 > 1 and t1.col6 > 1 and t1.col7 > 1 and t1.col8 > 1 and t1.col9 > 1 and t1.col10 > 1 and t1.col11 > 1 and t1.col12 > 1 and t1.col13 > 1 and t1.col14 > 1 and t1.col15 > 1 and t1.col16 > 1 and t1.col17 > 1 and t1.col18 > 1 and t1.col19 > 1 and t1.col20 > 1 and t1.col21 > 1 and t1.col22 > 1 and t1.col23 > 1 and t1.col24 > 1 and t1.col25 > 1 and t1.col26 > 1 and t1.col27 > 1 and t1.col28 > 1 and t1.col29 > 1 and t1.col30 > 1 and t1.col31 > 1 and t1.col32 > 1 and t1.col33 > 1 and t1.col34 > 1 and t1.col35 > 1 and t1.col36 > 1 and t1.col37 > 1 and t1.col38 > 1 and t1.col39 > 1 and t1.col40 > 1 and t1.col41 > 1 and t1.col42 > 1 and t1.col43 > 1 and t1.col44 > 1 and t1.col45 > 1 and t1.col46 > 1 and t1.col47 > 1 and t1.col48 > 1 and t1.col49 > 1 and t1.col50 > 1 and t1.col51 > 1 and t1.col52 > 1 and t1.col53 > 1 and t1.col54 > 1 and t1.col55 > 1 and t1.col56 > 1 and t1.col57 > 1 and t1.col58 > 1 and t1.col59 > 1 and t1.col60 > 1 and t1.col61 > 1 and t1.col62 > 1 and t1.col63 > 1 and t1.col64 > 1 and t1.col65 > 1 and t1.col66 > 1 and t1.col67 > 1 and t1.col68 > 1 and t1.col69 > 1 and t1.col70 > 1 and t1.col71 > 1 and t1.col72 > 1 and t1.col73 > 1 and t1.col74 > 1 and t1.col75 > 1 and t1.col76 > 1 and t1.col77 > 1 and t1.col78 > 1 and t1.col79 > 1 and t1.col80 > 1 and t1.col81 > 1 and t1.col82 > 1 and t1.col83 > 1 and t1.col84 > 1 and t1.col85 > 1 and t1.col86 > 1 and t1.col87 > 1 and t1.col88 > 1 and t1.col89 > 1 and t1.col90 > 1 and t1.col91 > 1 and t1.col92 > 1 and t1.col93 > 1 and t1.col94 > 1 and t1.col95 > 1 and t1.col96 > 1 and t1.col97 > 1 and t1.col98 > 1 and t1.col99 > 1 and t1.col100 > 1 and t1.col101 > 1 and t1.col102 > 1 and t1.col103 > 1 and t1.col104 > 1 and t1.col105 > 1 and t1.col106 > 1 and t1.col107 > 1 and t1.col108 > 1 and t1.col109 > 1 and t1.col110 > 1 and t1.col111 > 1 and t1.col112 > 1 and t1.col113 > 1 and t1.col114 > 1 and t1.col115 > 1 and t1.col116 > 1 and t1.col117 > 1 and t1.col118 > 1 and t1.col119 > 1 and t1.col120 > 1 and t1.col121 > 1 and t1.col122 > 1 and t1.col123 > 1 and t1.col124 > 1 and t1.col125 > 1 and t1.col126 > 1 and t1.col127 > 1 and t1.col128 > 1 and t1.col129 > 1 and t1.col130 > 1 and t1.col131 > 1 and t1.col132 > 1 and t1.col133 > 1 and t1.col134 > 1 and t1.col135 > 1 and t1.col136 > 1 and t1.col137 > 1 and t1.col138 > 1 and t1.col139 > 1 and t1.col140 > 1 and t1.col141 > 1 and t1.col142 > 1 and t1.col143 > 1 and t1.col144 > 1 and t1.col145 > 1 and t1.col146 > 1 and t1.col147 > 1 and t1.col148 > 1 and t1.col149 > 1 and t1.col150 > 1 and t1.col151 > 1 and t1.col152 > 1 and t1.col153 > 1 and t1.col154 > 1 and t1.col155 > 1 and t1.col156 > 1 and t1.col157 > 1 and t1.col158 > 1 and t1.col159 > 1" + } + } + ] + } +} +select +json_detailed(json_extract(trace,'$**.selectivity_for_columns[0]')) as JS +from +information_schema.optimizer_trace; +JS +[ + { + "column_name": "col0", + "ranges": + ["1 < col0"], + "selectivity_from_histogram": 0.996078431 + } +] +$query_tbl; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.0322836, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "ALL", + "loops": 1, + "rows": 100, + "cost": 0.0322836, + "filtered": 53.32928848, + "attached_condition": "t1.col0 > 1 and t1.col1 > 1 and t1.col2 > 1 and t1.col3 > 1 and t1.col4 > 1 and t1.col5 > 1 and t1.col6 > 1 and t1.col7 > 1 and t1.col8 > 1 and t1.col9 > 1 and t1.col10 > 1 and t1.col11 > 1 and t1.col12 > 1 and t1.col13 > 1 and t1.col14 > 1 and t1.col15 > 1 and t1.col16 > 1 and t1.col17 > 1 and t1.col18 > 1 and t1.col19 > 1 and t1.col20 > 1 and t1.col21 > 1 and t1.col22 > 1 and t1.col23 > 1 and t1.col24 > 1 and t1.col25 > 1 and t1.col26 > 1 and t1.col27 > 1 and t1.col28 > 1 and t1.col29 > 1 and t1.col30 > 1 and t1.col31 > 1 and t1.col32 > 1 and t1.col33 > 1 and t1.col34 > 1 and t1.col35 > 1 and t1.col36 > 1 and t1.col37 > 1 and t1.col38 > 1 and t1.col39 > 1 and t1.col40 > 1 and t1.col41 > 1 and t1.col42 > 1 and t1.col43 > 1 and t1.col44 > 1 and t1.col45 > 1 and t1.col46 > 1 and t1.col47 > 1 and t1.col48 > 1 and t1.col49 > 1 and t1.col50 > 1 and t1.col51 > 1 and t1.col52 > 1 and t1.col53 > 1 and t1.col54 > 1 and t1.col55 > 1 and t1.col56 > 1 and t1.col57 > 1 and t1.col58 > 1 and t1.col59 > 1 and t1.col60 > 1 and t1.col61 > 1 and t1.col62 > 1 and t1.col63 > 1 and t1.col64 > 1 and t1.col65 > 1 and t1.col66 > 1 and t1.col67 > 1 and t1.col68 > 1 and t1.col69 > 1 and t1.col70 > 1 and t1.col71 > 1 and t1.col72 > 1 and t1.col73 > 1 and t1.col74 > 1 and t1.col75 > 1 and t1.col76 > 1 and t1.col77 > 1 and t1.col78 > 1 and t1.col79 > 1 and t1.col80 > 1 and t1.col81 > 1 and t1.col82 > 1 and t1.col83 > 1 and t1.col84 > 1 and t1.col85 > 1 and t1.col86 > 1 and t1.col87 > 1 and t1.col88 > 1 and t1.col89 > 1 and t1.col90 > 1 and t1.col91 > 1 and t1.col92 > 1 and t1.col93 > 1 and t1.col94 > 1 and t1.col95 > 1 and t1.col96 > 1 and t1.col97 > 1 and t1.col98 > 1 and t1.col99 > 1 and t1.col100 > 1 and t1.col101 > 1 and t1.col102 > 1 and t1.col103 > 1 and t1.col104 > 1 and t1.col105 > 1 and t1.col106 > 1 and t1.col107 > 1 and t1.col108 > 1 and t1.col109 > 1 and t1.col110 > 1 and t1.col111 > 1 and t1.col112 > 1 and t1.col113 > 1 and t1.col114 > 1 and t1.col115 > 1 and t1.col116 > 1 and t1.col117 > 1 and t1.col118 > 1 and t1.col119 > 1 and t1.col120 > 1 and t1.col121 > 1 and t1.col122 > 1 and t1.col123 > 1 and t1.col124 > 1 and t1.col125 > 1 and t1.col126 > 1 and t1.col127 > 1 and t1.col128 > 1 and t1.col129 > 1 and t1.col130 > 1 and t1.col131 > 1 and t1.col132 > 1 and t1.col133 > 1 and t1.col134 > 1 and t1.col135 > 1 and t1.col136 > 1 and t1.col137 > 1 and t1.col138 > 1 and t1.col139 > 1 and t1.col140 > 1 and t1.col141 > 1 and t1.col142 > 1 and t1.col143 > 1 and t1.col144 > 1 and t1.col145 > 1 and t1.col146 > 1 and t1.col147 > 1 and t1.col148 > 1 and t1.col149 > 1 and t1.col150 > 1 and t1.col151 > 1 and t1.col152 > 1 and t1.col153 > 1 and t1.col154 > 1 and t1.col155 > 1 and t1.col156 > 1 and t1.col157 > 1 and t1.col158 > 1 and t1.col159 > 1" + } + } + ] + } +} +select +json_detailed(json_extract(trace,'$**.selectivity_for_columns[159]')) as JS +from +information_schema.optimizer_trace; +JS +[ + { + "column_name": "col159", + "ranges": + ["1 < col159"], + "selectivity_from_histogram": 0.996078431 + } +] +# +# Check if not being able to infer anything for the first MAX_KEY +# columns doesn't prevent further inferences. +# +# explain extended select * from t1 +# where (1>2 or col0>1 or col1>1 or ...) and col99>1 +# +$query_tbl; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.0322836, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "ALL", + "loops": 1, + "rows": 100, + "cost": 0.0322836, + "filtered": 99.60784149, + "attached_condition": "(t1.col1 > 1 or t1.col2 > 1 or t1.col3 > 1 or t1.col4 > 1 or t1.col5 > 1 or t1.col6 > 1 or t1.col7 > 1 or t1.col8 > 1 or t1.col9 > 1 or t1.col10 > 1 or t1.col11 > 1 or t1.col12 > 1 or t1.col13 > 1 or t1.col14 > 1 or t1.col15 > 1 or t1.col16 > 1 or t1.col17 > 1 or t1.col18 > 1 or t1.col19 > 1 or t1.col20 > 1 or t1.col21 > 1 or t1.col22 > 1 or t1.col23 > 1 or t1.col24 > 1 or t1.col25 > 1 or t1.col26 > 1 or t1.col27 > 1 or t1.col28 > 1 or t1.col29 > 1 or t1.col30 > 1 or t1.col31 > 1 or t1.col32 > 1 or t1.col33 > 1 or t1.col34 > 1 or t1.col35 > 1 or t1.col36 > 1 or t1.col37 > 1 or t1.col38 > 1 or t1.col39 > 1 or t1.col40 > 1 or t1.col41 > 1 or t1.col42 > 1 or t1.col43 > 1 or t1.col44 > 1 or t1.col45 > 1 or t1.col46 > 1 or t1.col47 > 1 or t1.col48 > 1 or t1.col49 > 1 or t1.col50 > 1 or t1.col51 > 1 or t1.col52 > 1 or t1.col53 > 1 or t1.col54 > 1 or t1.col55 > 1 or t1.col56 > 1 or t1.col57 > 1 or t1.col58 > 1 or t1.col59 > 1 or t1.col60 > 1 or t1.col61 > 1 or t1.col62 > 1 or t1.col63 > 1 or t1.col64 > 1 or t1.col65 > 1 or t1.col66 > 1 or t1.col67 > 1 or t1.col68 > 1 or t1.col69 > 1 or t1.col70 > 1 or t1.col71 > 1 or t1.col72 > 1 or t1.col73 > 1 or t1.col74 > 1 or t1.col75 > 1 or t1.col76 > 1 or t1.col77 > 1 or t1.col78 > 1 or t1.col79 > 1 or t1.col80 > 1 or t1.col81 > 1 or t1.col82 > 1 or t1.col83 > 1 or t1.col84 > 1 or t1.col85 > 1 or t1.col86 > 1 or t1.col87 > 1 or t1.col88 > 1 or t1.col89 > 1 or t1.col90 > 1 or t1.col91 > 1 or t1.col92 > 1 or t1.col93 > 1 or t1.col94 > 1 or t1.col95 > 1 or t1.col96 > 1 or t1.col97 > 1 or t1.col98 > 1 or t1.col99 > 1 or t1.col100 > 1 or t1.col101 > 1 or t1.col102 > 1 or t1.col103 > 1 or t1.col104 > 1 or t1.col105 > 1 or t1.col106 > 1 or t1.col107 > 1 or t1.col108 > 1 or t1.col109 > 1 or t1.col110 > 1 or t1.col111 > 1 or t1.col112 > 1 or t1.col113 > 1 or t1.col114 > 1 or t1.col115 > 1 or t1.col116 > 1 or t1.col117 > 1 or t1.col118 > 1 or t1.col119 > 1 or t1.col120 > 1 or t1.col121 > 1 or t1.col122 > 1 or t1.col123 > 1 or t1.col124 > 1 or t1.col125 > 1 or t1.col126 > 1 or t1.col127 > 1 or t1.col128 > 1 or t1.col129 > 1 or t1.col130 > 1 or t1.col131 > 1 or t1.col132 > 1 or t1.col133 > 1 or t1.col134 > 1 or t1.col135 > 1 or t1.col136 > 1 or t1.col137 > 1 or t1.col138 > 1 or t1.col139 > 1 or t1.col140 > 1 or t1.col141 > 1 or t1.col142 > 1 or t1.col143 > 1 or t1.col144 > 1 or t1.col145 > 1 or t1.col146 > 1 or t1.col147 > 1 or t1.col148 > 1 or t1.col149 > 1 or t1.col150 > 1 or t1.col151 > 1 or t1.col152 > 1 or t1.col153 > 1 or t1.col154 > 1 or t1.col155 > 1 or t1.col156 > 1 or t1.col157 > 1 or t1.col158 > 1) and t1.col159 > 1" + } + } + ] + } +} +select +json_detailed(json_extract(trace,'$**.selectivity_for_columns')) as JS +from +information_schema.optimizer_trace; +JS +[ + [ + { + "column_name": "col159", + "ranges": + ["1 < col159"], + "selectivity_from_histogram": 0.996078431 + } + ] +] +set optimizer_trace=@trace_tmp; +drop table t1; +# # Clean up # +set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; +set use_stat_tables= @save_use_stat_tables; set @@global.histogram_size=@save_histogram_size; set optimizer_switch=@save_optimizer_switch_for_selectivity_test; SET SESSION STORAGE_ENGINE=DEFAULT; diff --git a/mysql-test/main/selectivity_notembedded.result b/mysql-test/main/selectivity_notembedded.result index d2e90a19a68..d47154fd294 100644 --- a/mysql-test/main/selectivity_notembedded.result +++ b/mysql-test/main/selectivity_notembedded.result @@ -83,13 +83,149 @@ sel ] set optimizer_trace=@tmp; drop table t0,t1,t10; -set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; set histogram_size=@save_histogram_size; -set use_stat_tables= @save_use_stat_tables; # # End of 10.4 tests # # +# MDEV-33314: Crash inside calculate_cond_selectivity_for_table() with many columns +# +set optimizer_use_condition_selectivity= 4; +set use_stat_tables= preferably; +# +# create table t1 (col0 int, col1 int, col2 int, ...); +# +$create_tbl; +# +# insert into t1 select seq, ... seq from seq_1_to_10; +# +$insert_cmd; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +set @trace_tmp=@@optimizer_trace; +set optimizer_trace=1; +# +# Basic testcase: don't crash for many-column selectivity +# explain extended select * from t1 where col0>1 and col1>1 and col2>1 and ... +# +$query_tbl; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.0295225, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "ALL", + "loops": 1, + "rows": 100, + "cost": 0.0295225, + "filtered": 53.32928848, + "attached_condition": "t1.col0 > 1 and t1.col1 > 1 and t1.col2 > 1 and t1.col3 > 1 and t1.col4 > 1 and t1.col5 > 1 and t1.col6 > 1 and t1.col7 > 1 and t1.col8 > 1 and t1.col9 > 1 and t1.col10 > 1 and t1.col11 > 1 and t1.col12 > 1 and t1.col13 > 1 and t1.col14 > 1 and t1.col15 > 1 and t1.col16 > 1 and t1.col17 > 1 and t1.col18 > 1 and t1.col19 > 1 and t1.col20 > 1 and t1.col21 > 1 and t1.col22 > 1 and t1.col23 > 1 and t1.col24 > 1 and t1.col25 > 1 and t1.col26 > 1 and t1.col27 > 1 and t1.col28 > 1 and t1.col29 > 1 and t1.col30 > 1 and t1.col31 > 1 and t1.col32 > 1 and t1.col33 > 1 and t1.col34 > 1 and t1.col35 > 1 and t1.col36 > 1 and t1.col37 > 1 and t1.col38 > 1 and t1.col39 > 1 and t1.col40 > 1 and t1.col41 > 1 and t1.col42 > 1 and t1.col43 > 1 and t1.col44 > 1 and t1.col45 > 1 and t1.col46 > 1 and t1.col47 > 1 and t1.col48 > 1 and t1.col49 > 1 and t1.col50 > 1 and t1.col51 > 1 and t1.col52 > 1 and t1.col53 > 1 and t1.col54 > 1 and t1.col55 > 1 and t1.col56 > 1 and t1.col57 > 1 and t1.col58 > 1 and t1.col59 > 1 and t1.col60 > 1 and t1.col61 > 1 and t1.col62 > 1 and t1.col63 > 1 and t1.col64 > 1 and t1.col65 > 1 and t1.col66 > 1 and t1.col67 > 1 and t1.col68 > 1 and t1.col69 > 1 and t1.col70 > 1 and t1.col71 > 1 and t1.col72 > 1 and t1.col73 > 1 and t1.col74 > 1 and t1.col75 > 1 and t1.col76 > 1 and t1.col77 > 1 and t1.col78 > 1 and t1.col79 > 1 and t1.col80 > 1 and t1.col81 > 1 and t1.col82 > 1 and t1.col83 > 1 and t1.col84 > 1 and t1.col85 > 1 and t1.col86 > 1 and t1.col87 > 1 and t1.col88 > 1 and t1.col89 > 1 and t1.col90 > 1 and t1.col91 > 1 and t1.col92 > 1 and t1.col93 > 1 and t1.col94 > 1 and t1.col95 > 1 and t1.col96 > 1 and t1.col97 > 1 and t1.col98 > 1 and t1.col99 > 1 and t1.col100 > 1 and t1.col101 > 1 and t1.col102 > 1 and t1.col103 > 1 and t1.col104 > 1 and t1.col105 > 1 and t1.col106 > 1 and t1.col107 > 1 and t1.col108 > 1 and t1.col109 > 1 and t1.col110 > 1 and t1.col111 > 1 and t1.col112 > 1 and t1.col113 > 1 and t1.col114 > 1 and t1.col115 > 1 and t1.col116 > 1 and t1.col117 > 1 and t1.col118 > 1 and t1.col119 > 1 and t1.col120 > 1 and t1.col121 > 1 and t1.col122 > 1 and t1.col123 > 1 and t1.col124 > 1 and t1.col125 > 1 and t1.col126 > 1 and t1.col127 > 1 and t1.col128 > 1 and t1.col129 > 1 and t1.col130 > 1 and t1.col131 > 1 and t1.col132 > 1 and t1.col133 > 1 and t1.col134 > 1 and t1.col135 > 1 and t1.col136 > 1 and t1.col137 > 1 and t1.col138 > 1 and t1.col139 > 1 and t1.col140 > 1 and t1.col141 > 1 and t1.col142 > 1 and t1.col143 > 1 and t1.col144 > 1 and t1.col145 > 1 and t1.col146 > 1 and t1.col147 > 1 and t1.col148 > 1 and t1.col149 > 1 and t1.col150 > 1 and t1.col151 > 1 and t1.col152 > 1 and t1.col153 > 1 and t1.col154 > 1 and t1.col155 > 1 and t1.col156 > 1 and t1.col157 > 1 and t1.col158 > 1 and t1.col159 > 1" + } + } + ] + } +} +select +json_detailed(json_extract(trace,'$**.selectivity_for_columns[0]')) as JS +from +information_schema.optimizer_trace; +JS +[ + { + "column_name": "col0", + "ranges": + ["1 < col0"], + "selectivity_from_histogram": 0.996078431 + } +] +$query_tbl; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.0295225, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "ALL", + "loops": 1, + "rows": 100, + "cost": 0.0295225, + "filtered": 53.32928848, + "attached_condition": "t1.col0 > 1 and t1.col1 > 1 and t1.col2 > 1 and t1.col3 > 1 and t1.col4 > 1 and t1.col5 > 1 and t1.col6 > 1 and t1.col7 > 1 and t1.col8 > 1 and t1.col9 > 1 and t1.col10 > 1 and t1.col11 > 1 and t1.col12 > 1 and t1.col13 > 1 and t1.col14 > 1 and t1.col15 > 1 and t1.col16 > 1 and t1.col17 > 1 and t1.col18 > 1 and t1.col19 > 1 and t1.col20 > 1 and t1.col21 > 1 and t1.col22 > 1 and t1.col23 > 1 and t1.col24 > 1 and t1.col25 > 1 and t1.col26 > 1 and t1.col27 > 1 and t1.col28 > 1 and t1.col29 > 1 and t1.col30 > 1 and t1.col31 > 1 and t1.col32 > 1 and t1.col33 > 1 and t1.col34 > 1 and t1.col35 > 1 and t1.col36 > 1 and t1.col37 > 1 and t1.col38 > 1 and t1.col39 > 1 and t1.col40 > 1 and t1.col41 > 1 and t1.col42 > 1 and t1.col43 > 1 and t1.col44 > 1 and t1.col45 > 1 and t1.col46 > 1 and t1.col47 > 1 and t1.col48 > 1 and t1.col49 > 1 and t1.col50 > 1 and t1.col51 > 1 and t1.col52 > 1 and t1.col53 > 1 and t1.col54 > 1 and t1.col55 > 1 and t1.col56 > 1 and t1.col57 > 1 and t1.col58 > 1 and t1.col59 > 1 and t1.col60 > 1 and t1.col61 > 1 and t1.col62 > 1 and t1.col63 > 1 and t1.col64 > 1 and t1.col65 > 1 and t1.col66 > 1 and t1.col67 > 1 and t1.col68 > 1 and t1.col69 > 1 and t1.col70 > 1 and t1.col71 > 1 and t1.col72 > 1 and t1.col73 > 1 and t1.col74 > 1 and t1.col75 > 1 and t1.col76 > 1 and t1.col77 > 1 and t1.col78 > 1 and t1.col79 > 1 and t1.col80 > 1 and t1.col81 > 1 and t1.col82 > 1 and t1.col83 > 1 and t1.col84 > 1 and t1.col85 > 1 and t1.col86 > 1 and t1.col87 > 1 and t1.col88 > 1 and t1.col89 > 1 and t1.col90 > 1 and t1.col91 > 1 and t1.col92 > 1 and t1.col93 > 1 and t1.col94 > 1 and t1.col95 > 1 and t1.col96 > 1 and t1.col97 > 1 and t1.col98 > 1 and t1.col99 > 1 and t1.col100 > 1 and t1.col101 > 1 and t1.col102 > 1 and t1.col103 > 1 and t1.col104 > 1 and t1.col105 > 1 and t1.col106 > 1 and t1.col107 > 1 and t1.col108 > 1 and t1.col109 > 1 and t1.col110 > 1 and t1.col111 > 1 and t1.col112 > 1 and t1.col113 > 1 and t1.col114 > 1 and t1.col115 > 1 and t1.col116 > 1 and t1.col117 > 1 and t1.col118 > 1 and t1.col119 > 1 and t1.col120 > 1 and t1.col121 > 1 and t1.col122 > 1 and t1.col123 > 1 and t1.col124 > 1 and t1.col125 > 1 and t1.col126 > 1 and t1.col127 > 1 and t1.col128 > 1 and t1.col129 > 1 and t1.col130 > 1 and t1.col131 > 1 and t1.col132 > 1 and t1.col133 > 1 and t1.col134 > 1 and t1.col135 > 1 and t1.col136 > 1 and t1.col137 > 1 and t1.col138 > 1 and t1.col139 > 1 and t1.col140 > 1 and t1.col141 > 1 and t1.col142 > 1 and t1.col143 > 1 and t1.col144 > 1 and t1.col145 > 1 and t1.col146 > 1 and t1.col147 > 1 and t1.col148 > 1 and t1.col149 > 1 and t1.col150 > 1 and t1.col151 > 1 and t1.col152 > 1 and t1.col153 > 1 and t1.col154 > 1 and t1.col155 > 1 and t1.col156 > 1 and t1.col157 > 1 and t1.col158 > 1 and t1.col159 > 1" + } + } + ] + } +} +select +json_detailed(json_extract(trace,'$**.selectivity_for_columns[159]')) as JS +from +information_schema.optimizer_trace; +JS +[ + { + "column_name": "col159", + "ranges": + ["1 < col159"], + "selectivity_from_histogram": 0.996078431 + } +] +# +# Check if not being able to infer anything for the first MAX_KEY +# columns doesn't prevent further inferences. +# +# explain extended select * from t1 +# where (1>2 or col0>1 or col1>1 or ...) and col99>1 +# +$query_tbl; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.0295225, + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "ALL", + "loops": 1, + "rows": 100, + "cost": 0.0295225, + "filtered": 99.60784149, + "attached_condition": "(t1.col1 > 1 or t1.col2 > 1 or t1.col3 > 1 or t1.col4 > 1 or t1.col5 > 1 or t1.col6 > 1 or t1.col7 > 1 or t1.col8 > 1 or t1.col9 > 1 or t1.col10 > 1 or t1.col11 > 1 or t1.col12 > 1 or t1.col13 > 1 or t1.col14 > 1 or t1.col15 > 1 or t1.col16 > 1 or t1.col17 > 1 or t1.col18 > 1 or t1.col19 > 1 or t1.col20 > 1 or t1.col21 > 1 or t1.col22 > 1 or t1.col23 > 1 or t1.col24 > 1 or t1.col25 > 1 or t1.col26 > 1 or t1.col27 > 1 or t1.col28 > 1 or t1.col29 > 1 or t1.col30 > 1 or t1.col31 > 1 or t1.col32 > 1 or t1.col33 > 1 or t1.col34 > 1 or t1.col35 > 1 or t1.col36 > 1 or t1.col37 > 1 or t1.col38 > 1 or t1.col39 > 1 or t1.col40 > 1 or t1.col41 > 1 or t1.col42 > 1 or t1.col43 > 1 or t1.col44 > 1 or t1.col45 > 1 or t1.col46 > 1 or t1.col47 > 1 or t1.col48 > 1 or t1.col49 > 1 or t1.col50 > 1 or t1.col51 > 1 or t1.col52 > 1 or t1.col53 > 1 or t1.col54 > 1 or t1.col55 > 1 or t1.col56 > 1 or t1.col57 > 1 or t1.col58 > 1 or t1.col59 > 1 or t1.col60 > 1 or t1.col61 > 1 or t1.col62 > 1 or t1.col63 > 1 or t1.col64 > 1 or t1.col65 > 1 or t1.col66 > 1 or t1.col67 > 1 or t1.col68 > 1 or t1.col69 > 1 or t1.col70 > 1 or t1.col71 > 1 or t1.col72 > 1 or t1.col73 > 1 or t1.col74 > 1 or t1.col75 > 1 or t1.col76 > 1 or t1.col77 > 1 or t1.col78 > 1 or t1.col79 > 1 or t1.col80 > 1 or t1.col81 > 1 or t1.col82 > 1 or t1.col83 > 1 or t1.col84 > 1 or t1.col85 > 1 or t1.col86 > 1 or t1.col87 > 1 or t1.col88 > 1 or t1.col89 > 1 or t1.col90 > 1 or t1.col91 > 1 or t1.col92 > 1 or t1.col93 > 1 or t1.col94 > 1 or t1.col95 > 1 or t1.col96 > 1 or t1.col97 > 1 or t1.col98 > 1 or t1.col99 > 1 or t1.col100 > 1 or t1.col101 > 1 or t1.col102 > 1 or t1.col103 > 1 or t1.col104 > 1 or t1.col105 > 1 or t1.col106 > 1 or t1.col107 > 1 or t1.col108 > 1 or t1.col109 > 1 or t1.col110 > 1 or t1.col111 > 1 or t1.col112 > 1 or t1.col113 > 1 or t1.col114 > 1 or t1.col115 > 1 or t1.col116 > 1 or t1.col117 > 1 or t1.col118 > 1 or t1.col119 > 1 or t1.col120 > 1 or t1.col121 > 1 or t1.col122 > 1 or t1.col123 > 1 or t1.col124 > 1 or t1.col125 > 1 or t1.col126 > 1 or t1.col127 > 1 or t1.col128 > 1 or t1.col129 > 1 or t1.col130 > 1 or t1.col131 > 1 or t1.col132 > 1 or t1.col133 > 1 or t1.col134 > 1 or t1.col135 > 1 or t1.col136 > 1 or t1.col137 > 1 or t1.col138 > 1 or t1.col139 > 1 or t1.col140 > 1 or t1.col141 > 1 or t1.col142 > 1 or t1.col143 > 1 or t1.col144 > 1 or t1.col145 > 1 or t1.col146 > 1 or t1.col147 > 1 or t1.col148 > 1 or t1.col149 > 1 or t1.col150 > 1 or t1.col151 > 1 or t1.col152 > 1 or t1.col153 > 1 or t1.col154 > 1 or t1.col155 > 1 or t1.col156 > 1 or t1.col157 > 1 or t1.col158 > 1) and t1.col159 > 1" + } + } + ] + } +} +select +json_detailed(json_extract(trace,'$**.selectivity_for_columns')) as JS +from +information_schema.optimizer_trace; +JS +[ + [ + { + "column_name": "col159", + "ranges": + ["1 < col159"], + "selectivity_from_histogram": 0.996078431 + } + ] +] +set optimizer_trace=@trace_tmp; +drop table t1; +# # Clean up # +set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; +set use_stat_tables= @save_use_stat_tables; set @@global.histogram_size=@save_histogram_size; diff --git a/mysql-test/main/selectivity_notembedded.test b/mysql-test/main/selectivity_notembedded.test index 6752bd3c7e1..30e0b7f0d2f 100644 --- a/mysql-test/main/selectivity_notembedded.test +++ b/mysql-test/main/selectivity_notembedded.test @@ -105,17 +105,113 @@ from information_schema.optimizer_trace; set optimizer_trace=@tmp; drop table t0,t1,t10; -set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; set histogram_size=@save_histogram_size; -set use_stat_tables= @save_use_stat_tables; - --echo # --echo # End of 10.4 tests --echo # +--echo # +--echo # MDEV-33314: Crash inside calculate_cond_selectivity_for_table() with many columns +--echo # +set optimizer_use_condition_selectivity= 4; +set use_stat_tables= preferably; + +let $N_CONDS=160; +let $N_LAST_COND=159; +--echo # +--echo # create table t1 (col0 int, col1 int, col2 int, ...); +--echo # +let $create_tbl= create table t1 ( col0 int; +let $i=1; + +while ($i < $N_CONDS) { + let $create_tbl= $create_tbl, col$i int; + let $i=`select $i + 1`; +} + +let $create_tbl= $create_tbl ); +#echo $create_tbl; +evalp $create_tbl; + + +--echo # +--echo # insert into t1 select seq, ... seq from seq_1_to_10; +--echo # +let $insert_cmd= insert into t1 select seq; +let $i=1; + +while ($i < $N_CONDS) { + let $insert_cmd = $insert_cmd ,seq; + let $i=`select $i + 1`; +} +let $insert_cmd= $insert_cmd from seq_1_to_100; + +# echo $insert_cmd; +evalp $insert_cmd; + +analyze table t1 persistent for all; +set @trace_tmp=@@optimizer_trace; +set optimizer_trace=1; + +--echo # +--echo # Basic testcase: don't crash for many-column selectivity +--echo # explain extended select * from t1 where col0>1 and col1>1 and col2>1 and ... +--echo # +let $query_tbl= explain format=json select * from t1 where col0>1; + +let $i=1; +while ($i < $N_CONDS) { + let $query_tbl= $query_tbl and col$i>1; + let $i=`select $i + 1`; +} + +#echo $query_tbl; +evalp $query_tbl; + +select + json_detailed(json_extract(trace,'$**.selectivity_for_columns[0]')) as JS +from + information_schema.optimizer_trace; + +evalp $query_tbl; +eval select + json_detailed(json_extract(trace,'\$**.selectivity_for_columns[$N_LAST_COND]')) as JS +from + information_schema.optimizer_trace; + + +--echo # +--echo # Check if not being able to infer anything for the first MAX_KEY +--echo # columns doesn't prevent further inferences. +--echo # +--echo # explain extended select * from t1 +--echo # where (1>2 or col0>1 or col1>1 or ...) and col99>1 +--echo # +let $query_tbl= explain format=json select * from t1 where (1>2 ; + +let $i=1; +while ($i < $N_LAST_COND) { + let $query_tbl= $query_tbl or col$i>1; + let $i=`select $i + 1`; +} +let $query_tbl= $query_tbl) and col$N_LAST_COND>1; + +#echo $query_tbl; +evalp $query_tbl; + +select + json_detailed(json_extract(trace,'$**.selectivity_for_columns')) as JS +from + information_schema.optimizer_trace; + +set optimizer_trace=@trace_tmp; +drop table t1; + --echo # --echo # Clean up --echo # --source include/restore_charset.inc +set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; +set use_stat_tables= @save_use_stat_tables; set @@global.histogram_size=@save_histogram_size; diff --git a/mysql-test/main/show_analyze.result b/mysql-test/main/show_analyze.result index dc5ef3cb22a..b730a2cc472 100644 --- a/mysql-test/main/show_analyze.result +++ b/mysql-test/main/show_analyze.result @@ -207,9 +207,12 @@ id select_type table type possible_keys key key_len ref rows r_rows filtered r_f SET debug_dbug=@old_debug; # Try to do SHOW ANALYZE for a query that runs a SET command: # -set @show_explain_probe_select_id=2; +create table t2 (a int); +insert into t2 values (1),(2); +set @show_explain_probe_select_id=3; SET debug_dbug='+d,show_explain_probe_join_exec_start'; -set @foo= (select max(a) from t0 where sin(a) >0); +set @foo= (select max(a) from t2 +where a + (select max(a) from t0 where t0.a>t2.a) < 10000); connection default; show analyze for $thr2; ERROR HY000: Target is not executing an operation with a query plan @@ -217,6 +220,7 @@ kill query $thr2; connection con1; ERROR 70100: Query execution was interrupted SET debug_dbug=@old_debug; +drop table t2; # # Attempt SHOW ANALYZE for an UPDATE # diff --git a/mysql-test/main/show_analyze.test b/mysql-test/main/show_analyze.test index 58d36d7dd16..c55aacdac77 100644 --- a/mysql-test/main/show_analyze.test +++ b/mysql-test/main/show_analyze.test @@ -213,9 +213,15 @@ SET debug_dbug=@old_debug; --echo # Try to do SHOW ANALYZE for a query that runs a SET command: --echo # -set @show_explain_probe_select_id=2; # <--- +create table t2 (a int); +insert into t2 values (1),(2); +set @show_explain_probe_select_id=3; # Stop in the subquery. SET debug_dbug='+d,show_explain_probe_join_exec_start'; -send set @foo= (select max(a) from t0 where sin(a) >0); +# t2 has 2 rows so we will stop in the subquery twice: +# - first one to serve the SHOW ANALYZE request +# - second one when waiting to be KILLed. +send set @foo= (select max(a) from t2 + where a + (select max(a) from t0 where t0.a>t2.a) < 10000); connection default; --source include/wait_condition.inc --error ER_TARGET_NOT_EXPLAINABLE @@ -225,7 +231,7 @@ connection con1; --error ER_QUERY_INTERRUPTED reap; SET debug_dbug=@old_debug; - +drop table t2; --echo # --echo # Attempt SHOW ANALYZE for an UPDATE diff --git a/mysql-test/main/stat_tables_partition.result b/mysql-test/main/stat_tables_partition.result index 2619026b231..2dd63e858d4 100644 --- a/mysql-test/main/stat_tables_partition.result +++ b/mysql-test/main/stat_tables_partition.result @@ -34,13 +34,12 @@ set session use_stat_tables='preferably'; # Must NOT show "Engine-independent statistics collected": alter table t1 analyze partition p0; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK # Should not have Handler_read_rnd_next=34 show session status like 'Handler_read_rnd%'; Variable_name Value Handler_read_rnd 0 Handler_read_rnd_deleted 0 -Handler_read_rnd_next 34 +Handler_read_rnd_next 0 drop table t1; SET use_stat_tables = DEFAULT; diff --git a/mysql-test/main/stat_tables_rbr.result b/mysql-test/main/stat_tables_rbr.result index 38f774412bd..9d5e7f85530 100644 --- a/mysql-test/main/stat_tables_rbr.result +++ b/mysql-test/main/stat_tables_rbr.result @@ -17,7 +17,6 @@ SET use_stat_tables = PREFERABLY; CREATE TABLE t1 ( a INT ) ENGINE=MyISAM PARTITION BY HASH(a) PARTITIONS 2; ALTER TABLE t1 ANALYZE PARTITION p1; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK include/show_binlog_events.inc Log_name Pos Event_type Server_id End_log_pos Info diff --git a/mysql-test/main/table_value_constr.result b/mysql-test/main/table_value_constr.result index 6d8dd6826e8..857808f6b60 100644 --- a/mysql-test/main/table_value_constr.result +++ b/mysql-test/main/table_value_constr.result @@ -2617,9 +2617,9 @@ ERROR HY000: 'ignore' is not allowed in this context VALUES (DEFAULT); ERROR HY000: 'default' is not allowed in this context EXECUTE IMMEDIATE 'VALUES (?)' USING IGNORE; -ERROR HY000: 'ignore' is not allowed in this context +ERROR HY000: Default/ignore value is not supported for such parameter usage EXECUTE IMMEDIATE 'VALUES (?)' USING DEFAULT; -ERROR HY000: 'default' is not allowed in this context +ERROR HY000: Default/ignore value is not supported for such parameter usage # # MDEV-24675: TVC using subqueries # diff --git a/mysql-test/main/table_value_constr.test b/mysql-test/main/table_value_constr.test index ac623eaaf0b..29347a16f98 100644 --- a/mysql-test/main/table_value_constr.test +++ b/mysql-test/main/table_value_constr.test @@ -1368,9 +1368,9 @@ DELIMITER ;$$ VALUES (IGNORE); --error ER_NOT_ALLOWED_IN_THIS_CONTEXT VALUES (DEFAULT); ---error ER_NOT_ALLOWED_IN_THIS_CONTEXT +--error ER_INVALID_DEFAULT_PARAM EXECUTE IMMEDIATE 'VALUES (?)' USING IGNORE; ---error ER_NOT_ALLOWED_IN_THIS_CONTEXT +--error ER_INVALID_DEFAULT_PARAM EXECUTE IMMEDIATE 'VALUES (?)' USING DEFAULT; --echo # diff --git a/mysql-test/main/udf.result b/mysql-test/main/udf.result index 8dc24a8dd38..53abd9c11c1 100644 --- a/mysql-test/main/udf.result +++ b/mysql-test/main/udf.result @@ -607,4 +607,68 @@ drop table t1; DROP FUNCTION avgcost; DROP FUNCTION avg2; DROP FUNCTION myfunc_double; +# +# MDEV-24507: Server Crash using UDF in WHERE clause of VIEW +# +CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB"; +create table t1(pk int primary key, a varchar(20)); +create table t2(pk int primary key, a varchar(20)); +create view v1 as select pk, a from t1 union select pk, a from t2; +insert into t1 values (1, "One"), (3, "Three"), (5, "Five"); +insert into t2 values (2, "Dos"), (4, "Quatro"), (6, "Seis"); +select pk, myfunc_int(a) from t1; +pk myfunc_int(a) +1 3 +3 5 +5 4 +select pk, myfunc_int(a) from t2; +pk myfunc_int(a) +2 3 +4 6 +6 4 +select pk, myfunc_int(a) from v1; +pk myfunc_int(a) +1 3 +3 5 +5 4 +2 3 +4 6 +6 4 +select pk from t1 where myfunc_int(a) > 4; +pk +3 +select pk from (select pk, a from t1) A where myfunc_int(A.a) > 4; +pk +3 +set @save_optimizer_switch = @@optimizer_switch; +set optimizer_switch = 'derived_merge=OFF'; +select pk, myfunc_int(a) from t1; +pk myfunc_int(a) +1 3 +3 5 +5 4 +select pk, myfunc_int(a) from t2; +pk myfunc_int(a) +2 3 +4 6 +6 4 +select pk, myfunc_int(a) from v1; +pk myfunc_int(a) +1 3 +3 5 +5 4 +2 3 +4 6 +6 4 +select pk from t1 where myfunc_int(a) > 4; +pk +3 +select pk from (select pk, a from t1) A where myfunc_int(A.a) > 4; +pk +3 +set optimizer_switch = @save_optimizer_switch; +drop view v1; +drop table t2; +drop table t1; +drop function myfunc_int; # End of 10.4 tests diff --git a/mysql-test/main/udf.test b/mysql-test/main/udf.test index e9823a31863..d87d446f733 100644 --- a/mysql-test/main/udf.test +++ b/mysql-test/main/udf.test @@ -647,4 +647,38 @@ DROP FUNCTION avgcost; DROP FUNCTION avg2; DROP FUNCTION myfunc_double; +--echo # +--echo # MDEV-24507: Server Crash using UDF in WHERE clause of VIEW +--echo # + +--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB +eval CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "$UDF_EXAMPLE_SO"; + +create table t1(pk int primary key, a varchar(20)); +create table t2(pk int primary key, a varchar(20)); +create view v1 as select pk, a from t1 union select pk, a from t2; + +insert into t1 values (1, "One"), (3, "Three"), (5, "Five"); +insert into t2 values (2, "Dos"), (4, "Quatro"), (6, "Seis"); + +select pk, myfunc_int(a) from t1; +select pk, myfunc_int(a) from t2; +select pk, myfunc_int(a) from v1; +select pk from t1 where myfunc_int(a) > 4; +select pk from (select pk, a from t1) A where myfunc_int(A.a) > 4; + +set @save_optimizer_switch = @@optimizer_switch; +set optimizer_switch = 'derived_merge=OFF'; +select pk, myfunc_int(a) from t1; +select pk, myfunc_int(a) from t2; +select pk, myfunc_int(a) from v1; +select pk from t1 where myfunc_int(a) > 4; +select pk from (select pk, a from t1) A where myfunc_int(A.a) > 4; + +set optimizer_switch = @save_optimizer_switch; +drop view v1; +drop table t2; +drop table t1; +drop function myfunc_int; + --echo # End of 10.4 tests diff --git a/mysql-test/mariadb-test-run.pl b/mysql-test/mariadb-test-run.pl index eb9a400eb78..9f248d44b37 100755 --- a/mysql-test/mariadb-test-run.pl +++ b/mysql-test/mariadb-test-run.pl @@ -3104,7 +3104,7 @@ sub mysql_install_db { mtr_add_arg($args, "--core-file"); mtr_add_arg($args, "--console"); mtr_add_arg($args, "--character-set-server=latin1"); - mtr_add_arg($args, "--disable-performance-schema"); + mtr_add_arg($args, "--loose-disable-performance-schema"); if ( $opt_debug ) { 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/std_data/mdev-25731.dat b/mysql-test/std_data/mdev-25731.dat new file mode 100644 index 00000000000..e6c779a8292 --- /dev/null +++ b/mysql-test/std_data/mdev-25731.dat @@ -0,0 +1,6 @@ +1 +2 +3 +1 +5 +6 diff --git a/mysql-test/suite/encryption/r/corrupted_during_recovery.result b/mysql-test/suite/encryption/r/corrupted_during_recovery.result index 7329999dd27..8fef209ee7b 100644 --- a/mysql-test/suite/encryption/r/corrupted_during_recovery.result +++ b/mysql-test/suite/encryption/r/corrupted_during_recovery.result @@ -9,7 +9,7 @@ INSERT INTO t2 VALUES(2); SELECT * FROM t1; ERROR 42000: Unknown storage engine 'InnoDB' SELECT * FROM t1; -Got one of the listed errors +ERROR HY000: Table `test`.`t1` is corrupted. Please drop the table and recreate. SELECT * FROM t2; a 2 diff --git a/mysql-test/suite/encryption/r/innodb-bad-key-change.result b/mysql-test/suite/encryption/r/innodb-bad-key-change.result index eb114fcf6fc..613f9446be6 100644 --- a/mysql-test/suite/encryption/r/innodb-bad-key-change.result +++ b/mysql-test/suite/encryption/r/innodb-bad-key-change.result @@ -31,7 +31,7 @@ foobar 2 # Restart server with keysbad3.txt # restart: --file-key-management-filename=MYSQL_TEST_DIR/std_data/keysbad3.txt SELECT * FROM t1; -ERROR 42S02: Table 'test.t1' doesn't exist in engine +ERROR HY000: Table `test`.`t1` is corrupted. Please drop the table and recreate. # restart: --file-key-management-filename=MYSQL_TEST_DIR/std_data/keysbad3.txt DROP TABLE t1; # Start server with keys3.txt @@ -43,31 +43,31 @@ INSERT INTO t2 VALUES ('foobar',1,2); # Restart server with keys2.txt # restart: --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys2.txt SELECT * FROM t2; -ERROR 42S02: Table 'test.t2' doesn't exist in engine +ERROR HY000: Table `test`.`t2` is corrupted. Please drop the table and recreate. SELECT * FROM t2 where id = 1; -ERROR HY000: Table test/t2 is corrupted. Please drop the table and recreate. +ERROR HY000: Table `test`.`t2` is corrupted. Please drop the table and recreate. SELECT * FROM t2 where b = 1; -ERROR HY000: Table test/t2 is corrupted. Please drop the table and recreate. +ERROR HY000: Table `test`.`t2` is corrupted. Please drop the table and recreate. INSERT INTO t2 VALUES ('tmp',3,3); -ERROR HY000: Table test/t2 is corrupted. Please drop the table and recreate. +ERROR HY000: Table `test`.`t2` is corrupted. Please drop the table and recreate. DELETE FROM t2 where b = 3; -ERROR HY000: Table test/t2 is corrupted. Please drop the table and recreate. +ERROR HY000: Table `test`.`t2` is corrupted. Please drop the table and recreate. DELETE FROM t2 where id = 3; -ERROR HY000: Table test/t2 is corrupted. Please drop the table and recreate. +ERROR HY000: Table `test`.`t2` is corrupted. Please drop the table and recreate. UPDATE t2 set b = b +1; -ERROR HY000: Table test/t2 is corrupted. Please drop the table and recreate. +ERROR HY000: Table `test`.`t2` is corrupted. Please drop the table and recreate. OPTIMIZE TABLE t2; Table Op Msg_type Msg_text -test.t2 optimize Error Table test/t2 is corrupted. Please drop the table and recreate. +test.t2 optimize Error Table `test`.`t2` is corrupted. Please drop the table and recreate. test.t2 optimize error Corrupt ALTER TABLE t2 ADD COLUMN d INT; -ERROR HY000: Table test/t2 is corrupted. Please drop the table and recreate. +ERROR HY000: Table `test`.`t2` is corrupted. Please drop the table and recreate. ANALYZE TABLE t2; Table Op Msg_type Msg_text -test.t2 analyze Error Table test/t2 is corrupted. Please drop the table and recreate. +test.t2 analyze Error Table `test`.`t2` is corrupted. Please drop the table and recreate. test.t2 analyze error Corrupt TRUNCATE TABLE t2; -ERROR HY000: Table test/t2 is corrupted. Please drop the table and recreate. +ERROR HY000: Table `test`.`t2` is corrupted. Please drop the table and recreate. DROP TABLE t2; # Start server with keys2.txt diff --git a/mysql-test/suite/encryption/r/innodb-bad-key-change2.result b/mysql-test/suite/encryption/r/innodb-bad-key-change2.result index ab67b6fedad..129de6e9c46 100644 --- a/mysql-test/suite/encryption/r/innodb-bad-key-change2.result +++ b/mysql-test/suite/encryption/r/innodb-bad-key-change2.result @@ -13,24 +13,24 @@ ENCRYPTED=YES ENCRYPTION_KEY_ID=4; INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); # restart: --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys3.txt SELECT * FROM t1; -ERROR 42S02: Table 'test.t1' doesn't exist in engine +ERROR HY000: Table `test`.`t1` is corrupted. Please drop the table and recreate. SHOW WARNINGS; Level Code Message -Error 1932 Table 'test.t1' doesn't exist in engine +Error 1877 Table `test`.`t1` is corrupted. Please drop the table and recreate. ALTER TABLE t1 ENGINE=InnoDB; -ERROR HY000: Table test/t1 is corrupted. Please drop the table and recreate. +ERROR HY000: Table `test`.`t1` is corrupted. Please drop the table and recreate. SHOW WARNINGS; Level Code Message -Error 1877 Table test/t1 is corrupted. Please drop the table and recreate. +Error 1877 Table `test`.`t1` is corrupted. Please drop the table and recreate. OPTIMIZE TABLE t1; Table Op Msg_type Msg_text -test.t1 optimize Error Table test/t1 is corrupted. Please drop the table and recreate. +test.t1 optimize Error Table `test`.`t1` is corrupted. Please drop the table and recreate. test.t1 optimize error Corrupt SHOW WARNINGS; Level Code Message CHECK TABLE t1; Table Op Msg_type Msg_text -test.t1 check Error Table test/t1 is corrupted. Please drop the table and recreate. +test.t1 check Error Table `test`.`t1` is corrupted. Please drop the table and recreate. test.t1 check error Corrupt SHOW WARNINGS; Level Code Message @@ -40,7 +40,7 @@ backup: t1 UNLOCK TABLES; # restart: --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys3.txt ALTER TABLE t1 DISCARD TABLESPACE; -ERROR 42S02: Table 'test.t1' doesn't exist in engine +ERROR HY000: Table `test`.`t1` is corrupted. Please drop the table and recreate. DROP TABLE t1; CREATE TABLE t1 (pk INT PRIMARY KEY, f VARCHAR(8)) ENGINE=InnoDB ENCRYPTED=YES ENCRYPTION_KEY_ID=4; @@ -61,7 +61,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci `ENCRYPTED`=YES `ENCRYPTION_KEY_ID`=4 # restart: --innodb-encrypt-tables --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys3.txt RENAME TABLE t1 TO t1new; -ERROR HY000: Error on rename of './test/t1' to './test/t1new' (errno: 155 "The table does not exist in the storage engine") +ERROR HY000: Table `test`.`t1` is corrupted. Please drop the table and recreate. ALTER TABLE t1 RENAME TO t1new; -ERROR HY000: Table test/t1 is corrupted. Please drop the table and recreate. +ERROR HY000: Table `test`.`t1` is corrupted. Please drop the table and recreate. DROP TABLE t1; diff --git a/mysql-test/suite/encryption/r/innodb-bad-key-change4.result b/mysql-test/suite/encryption/r/innodb-bad-key-change4.result index 9983c26c9d7..747f6db8243 100644 --- a/mysql-test/suite/encryption/r/innodb-bad-key-change4.result +++ b/mysql-test/suite/encryption/r/innodb-bad-key-change4.result @@ -11,13 +11,13 @@ INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); # restart: --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys3.txt OPTIMIZE TABLE t1; Table Op Msg_type Msg_text -test.t1 optimize Error Table 'test.t1' doesn't exist in engine -test.t1 optimize status Operation failed +test.t1 optimize Error Table `test`.`t1` is corrupted. Please drop the table and recreate. +test.t1 optimize error Corrupt SHOW WARNINGS; Level Code Message CHECK TABLE t1; Table Op Msg_type Msg_text -test.t1 check Error Table test/t1 is corrupted. Please drop the table and recreate. +test.t1 check Error Table `test`.`t1` is corrupted. Please drop the table and recreate. test.t1 check error Corrupt SHOW WARNINGS; Level Code Message diff --git a/mysql-test/suite/encryption/r/innodb-compressed-blob.result b/mysql-test/suite/encryption/r/innodb-compressed-blob.result index bb87d171601..fd095f70bf2 100644 --- a/mysql-test/suite/encryption/r/innodb-compressed-blob.result +++ b/mysql-test/suite/encryption/r/innodb-compressed-blob.result @@ -1,7 +1,7 @@ call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[123]\\.ibd' cannot be decrypted; key_version=1"); call mtr.add_suppression("InnoDB: Recovery failed to read page"); call mtr.add_suppression("InnoDB: Unable to decompress ..test.t[1-3]\\.ibd\\[page id: space=[1-9][0-9]*, page number=[0-9]+\\]"); -call mtr.add_suppression("InnoDB: Table `test`\\.`t[12]` is corrupted"); +call mtr.add_suppression("Table `test`\\.`t[12]` is corrupted"); # Restart mysqld --file-key-management-filename=keys2.txt # restart: --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys2.txt set GLOBAL innodb_default_encryption_key_id=4; @@ -16,9 +16,9 @@ insert into t3 values (1, repeat('secret',6000)); # Restart mysqld --file-key-management-filename=keys3.txt # restart: --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys3.txt select count(*) from t1 FORCE INDEX (b) where b like 'secret%'; -ERROR 42S02: Table 'test.t1' doesn't exist in engine +ERROR HY000: Table `test`.`t1` is corrupted. Please drop the table and recreate. select count(*) from t2 FORCE INDEX (b) where b like 'secret%'; -ERROR 42S02: Table 'test.t2' doesn't exist in engine +ERROR HY000: Table `test`.`t2` is corrupted. Please drop the table and recreate. select count(*) from t3 FORCE INDEX (b) where b like 'secret%'; count(*) 1 diff --git a/mysql-test/suite/encryption/r/innodb-encryption-disable.result b/mysql-test/suite/encryption/r/innodb-encryption-disable.result index 179bc550617..86c6d63649f 100644 --- a/mysql-test/suite/encryption/r/innodb-encryption-disable.result +++ b/mysql-test/suite/encryption/r/innodb-encryption-disable.result @@ -1,8 +1,7 @@ -call mtr.add_suppression("InnoDB: Table `test`\\.`t[15]` (has an unreadable root page|is corrupted)"); +call mtr.add_suppression("Table `test`\\.`t[15]` (has an unreadable root page|is corrupted)"); call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[15]\\.ibd' cannot be decrypted\\."); call mtr.add_suppression("InnoDB: Recovery failed to read page"); call mtr.add_suppression("InnoDB: Encrypted page \\[page id: space=[1-9][0-9]*, page number=3\\] in file .*test.t[15].ibd looks corrupted; key_version=1"); -call mtr.add_suppression("InnoDB: Table `test`\\.`t[15]` is corrupted"); call mtr.add_suppression("Couldn't load plugins from 'file_key_management"); # restart: --innodb-encrypt-tables=ON --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys2.txt create table t5 ( @@ -24,9 +23,9 @@ insert into t1 values (1,2,'maria','db','encryption'); alter table t1 encrypted='yes' `encryption_key_id`=1; # restart: --innodb-encrypt-tables=OFF select * from t1; -ERROR 42S02: Table 'test.t1' doesn't exist in engine +ERROR HY000: Table `test`.`t1` is corrupted. Please drop the table and recreate. select * from t5; -ERROR 42S02: Table 'test.t5' doesn't exist in engine +ERROR HY000: Table `test`.`t5` is corrupted. Please drop the table and recreate. # restart: --innodb-encrypt-tables=ON --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys2.txt drop table t1; drop table t5; diff --git a/mysql-test/suite/encryption/r/innodb-force-corrupt.result b/mysql-test/suite/encryption/r/innodb-force-corrupt.result index 219dbd7cfc3..40b85bebabb 100644 --- a/mysql-test/suite/encryption/r/innodb-force-corrupt.result +++ b/mysql-test/suite/encryption/r/innodb-force-corrupt.result @@ -1,4 +1,4 @@ -call mtr.add_suppression("InnoDB: Table `test`\\.`t[13]` (has an unreadable root page|is corrupted)"); +call mtr.add_suppression("Table `test`\\.`t[13]` (has an unreadable root page|is corrupted)"); call mtr.add_suppression("InnoDB: Encrypted page \\[page id: space=\\d+, page number=[36]\\] in file .*test.t[123]\\.ibd looks corrupted; key_version="); call mtr.add_suppression("\\[ERROR\\] InnoDB: We detected index corruption in an InnoDB type table"); call mtr.add_suppression("\\[ERROR\\] (mysqld|mariadbd).*: Index for table 't2' is corrupt; try to repair it"); @@ -17,11 +17,11 @@ COMMIT; # Corrupt tables # restart SELECT * FROM t1; -ERROR 42S02: Table 'test.t1' doesn't exist in engine +ERROR HY000: Table `test`.`t1` is corrupted. Please drop the table and recreate. SELECT * FROM t2; Got one of the listed errors SELECT * FROM t3; -ERROR 42S02: Table 'test.t3' doesn't exist in engine +ERROR HY000: Table `test`.`t3` is corrupted. Please drop the table and recreate. # Restore the original tables # restart DROP TABLE t1,t2,t3; diff --git a/mysql-test/suite/encryption/r/innodb-missing-key.result b/mysql-test/suite/encryption/r/innodb-missing-key.result index d5c1e079e96..83c9166d05b 100644 --- a/mysql-test/suite/encryption/r/innodb-missing-key.result +++ b/mysql-test/suite/encryption/r/innodb-missing-key.result @@ -38,11 +38,11 @@ SELECT COUNT(1) FROM t2; COUNT(1) 2048 SELECT COUNT(1) FROM t2,t1 where t2.a = t1.a; -ERROR 42S02: Table 'test.t1' doesn't exist in engine +ERROR HY000: Table `test`.`t1` is corrupted. Please drop the table and recreate. SELECT COUNT(1) FROM t1 where b = 'ab'; -ERROR HY000: Table test/t1 is corrupted. Please drop the table and recreate. +ERROR HY000: Table `test`.`t1` is corrupted. Please drop the table and recreate. SELECT COUNT(1) FROM t1; -ERROR HY000: Table test/t1 is corrupted. Please drop the table and recreate. +ERROR HY000: Table `test`.`t1` is corrupted. Please drop the table and recreate. # Start server with keys2.txt # restart: --file-key-management-filename=MYSQL_TEST_DIR/std_data/keys2.txt diff --git a/mysql-test/suite/encryption/r/innodb-redo-nokeys.result b/mysql-test/suite/encryption/r/innodb-redo-nokeys.result index e503cb9a95c..cd17bd508dd 100644 --- a/mysql-test/suite/encryption/r/innodb-redo-nokeys.result +++ b/mysql-test/suite/encryption/r/innodb-redo-nokeys.result @@ -22,6 +22,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; @@ -41,6 +50,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/corrupted_during_recovery.test b/mysql-test/suite/encryption/t/corrupted_during_recovery.test index 1240ee1a8ff..e4a31a0b478 100644 --- a/mysql-test/suite/encryption/t/corrupted_during_recovery.test +++ b/mysql-test/suite/encryption/t/corrupted_during_recovery.test @@ -60,7 +60,7 @@ call mtr.add_suppression("Table .*t1.* is corrupted. Please drop the table and r let $restart_parameters=--innodb_force_recovery=1 --skip-innodb-buffer-pool-load-at-startup; --source include/restart_mysqld.inc ---error ER_NO_SUCH_TABLE_IN_ENGINE,ER_TABLE_CORRUPT +--error ER_TABLE_CORRUPT SELECT * FROM t1; SELECT * FROM t2; CHECK TABLE t2; diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change.test b/mysql-test/suite/encryption/t/innodb-bad-key-change.test index 5eefded9ae1..ee4f2e34947 100644 --- a/mysql-test/suite/encryption/t/innodb-bad-key-change.test +++ b/mysql-test/suite/encryption/t/innodb-bad-key-change.test @@ -41,7 +41,7 @@ SELECT * FROM t1; -- source include/restart_mysqld.inc --disable_warnings ---error ER_NO_SUCH_TABLE_IN_ENGINE +--error ER_TABLE_CORRUPT SELECT * FROM t1; --enable_warnings @@ -70,7 +70,7 @@ INSERT INTO t2 VALUES ('foobar',1,2); -- source include/restart_mysqld.inc --disable_warnings ---error ER_NO_SUCH_TABLE_IN_ENGINE +--error ER_TABLE_CORRUPT SELECT * FROM t2; --error ER_TABLE_CORRUPT diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change2.test b/mysql-test/suite/encryption/t/innodb-bad-key-change2.test index a6cc581e448..ac8e18b4980 100644 --- a/mysql-test/suite/encryption/t/innodb-bad-key-change2.test +++ b/mysql-test/suite/encryption/t/innodb-bad-key-change2.test @@ -30,7 +30,7 @@ INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); --let $restart_parameters=--plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys3.txt --source include/restart_mysqld.inc ---error ER_NO_SUCH_TABLE_IN_ENGINE +--error ER_TABLE_CORRUPT SELECT * FROM t1; --replace_regex /key_id [1-9][0-9]*/\1 / SHOW WARNINGS; @@ -61,7 +61,7 @@ UNLOCK TABLES; --let $restart_parameters=--plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys3.txt --source include/restart_mysqld.inc ---error ER_NO_SUCH_TABLE_IN_ENGINE +--error ER_TABLE_CORRUPT ALTER TABLE t1 DISCARD TABLESPACE; # Drop table will succeed. DROP TABLE t1; @@ -93,7 +93,7 @@ SHOW CREATE TABLE t1; --let $restart_parameters= --innodb-encrypt-tables --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys3.txt --source include/restart_mysqld.inc ---error ER_ERROR_ON_RENAME +--error ER_TABLE_CORRUPT RENAME TABLE t1 TO t1new; --error ER_TABLE_CORRUPT ALTER TABLE t1 RENAME TO t1new; diff --git a/mysql-test/suite/encryption/t/innodb-compressed-blob.test b/mysql-test/suite/encryption/t/innodb-compressed-blob.test index d3d53e2c41a..124b3ed17a2 100644 --- a/mysql-test/suite/encryption/t/innodb-compressed-blob.test +++ b/mysql-test/suite/encryption/t/innodb-compressed-blob.test @@ -7,7 +7,7 @@ call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[123]\\.ibd' cannot be decrypted; key_version=1"); call mtr.add_suppression("InnoDB: Recovery failed to read page"); call mtr.add_suppression("InnoDB: Unable to decompress ..test.t[1-3]\\.ibd\\[page id: space=[1-9][0-9]*, page number=[0-9]+\\]"); -call mtr.add_suppression("InnoDB: Table `test`\\.`t[12]` is corrupted"); +call mtr.add_suppression("Table `test`\\.`t[12]` is corrupted"); --echo # Restart mysqld --file-key-management-filename=keys2.txt -- let $restart_parameters=--file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt @@ -26,9 +26,9 @@ insert into t3 values (1, repeat('secret',6000)); -- let $restart_parameters=--file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys3.txt -- source include/restart_mysqld.inc ---error ER_NO_SUCH_TABLE_IN_ENGINE +--error ER_TABLE_CORRUPT select count(*) from t1 FORCE INDEX (b) where b like 'secret%'; ---error ER_NO_SUCH_TABLE_IN_ENGINE +--error ER_TABLE_CORRUPT select count(*) from t2 FORCE INDEX (b) where b like 'secret%'; select count(*) from t3 FORCE INDEX (b) where b like 'secret%'; diff --git a/mysql-test/suite/encryption/t/innodb-encryption-disable.test b/mysql-test/suite/encryption/t/innodb-encryption-disable.test index 939ad2b5547..7a7e590e304 100644 --- a/mysql-test/suite/encryption/t/innodb-encryption-disable.test +++ b/mysql-test/suite/encryption/t/innodb-encryption-disable.test @@ -7,11 +7,10 @@ # MDEV-9559: Server without encryption configs crashes if selecting from an implicitly encrypted table # -call mtr.add_suppression("InnoDB: Table `test`\\.`t[15]` (has an unreadable root page|is corrupted)"); +call mtr.add_suppression("Table `test`\\.`t[15]` (has an unreadable root page|is corrupted)"); call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\] in file '.*test.t[15]\\.ibd' cannot be decrypted\\."); call mtr.add_suppression("InnoDB: Recovery failed to read page"); call mtr.add_suppression("InnoDB: Encrypted page \\[page id: space=[1-9][0-9]*, page number=3\\] in file .*test.t[15].ibd looks corrupted; key_version=1"); -call mtr.add_suppression("InnoDB: Table `test`\\.`t[15]` is corrupted"); # Suppression for builds where file_key_management plugin is linked statically call mtr.add_suppression("Couldn't load plugins from 'file_key_management"); @@ -43,9 +42,9 @@ alter table t1 encrypted='yes' `encryption_key_id`=1; --let $restart_parameters=--innodb-encrypt-tables=OFF --source include/restart_mysqld.inc ---error ER_NO_SUCH_TABLE_IN_ENGINE +--error ER_TABLE_CORRUPT select * from t1; ---error ER_NO_SUCH_TABLE_IN_ENGINE +--error ER_TABLE_CORRUPT select * from t5; --let $restart_parameters=--innodb-encrypt-tables=ON --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt diff --git a/mysql-test/suite/encryption/t/innodb-force-corrupt.test b/mysql-test/suite/encryption/t/innodb-force-corrupt.test index 73fa0cde0cf..32205decf09 100644 --- a/mysql-test/suite/encryption/t/innodb-force-corrupt.test +++ b/mysql-test/suite/encryption/t/innodb-force-corrupt.test @@ -7,7 +7,7 @@ # Don't test under embedded -- source include/not_embedded.inc -call mtr.add_suppression("InnoDB: Table `test`\\.`t[13]` (has an unreadable root page|is corrupted)"); +call mtr.add_suppression("Table `test`\\.`t[13]` (has an unreadable root page|is corrupted)"); call mtr.add_suppression("InnoDB: Encrypted page \\[page id: space=\\d+, page number=[36]\\] in file .*test.t[123]\\.ibd looks corrupted; key_version="); call mtr.add_suppression("\\[ERROR\\] InnoDB: We detected index corruption in an InnoDB type table"); call mtr.add_suppression("\\[ERROR\\] (mysqld|mariadbd).*: Index for table 't2' is corrupt; try to repair it"); @@ -67,11 +67,11 @@ EOF --source include/start_mysqld.inc ---error ER_NO_SUCH_TABLE_IN_ENGINE +--error ER_TABLE_CORRUPT SELECT * FROM t1; --error ER_GET_ERRMSG,ER_NOT_KEYFILE SELECT * FROM t2; ---error ER_NO_SUCH_TABLE_IN_ENGINE +--error ER_TABLE_CORRUPT SELECT * FROM t3; --source include/shutdown_mysqld.inc diff --git a/mysql-test/suite/encryption/t/innodb-missing-key.test b/mysql-test/suite/encryption/t/innodb-missing-key.test index 53fc820a1c9..0c7a1df9ae2 100644 --- a/mysql-test/suite/encryption/t/innodb-missing-key.test +++ b/mysql-test/suite/encryption/t/innodb-missing-key.test @@ -46,7 +46,7 @@ CREATE TABLE t4(a int not null primary key auto_increment, b varchar(128)) engin SELECT SLEEP(5); SELECT COUNT(1) FROM t3; SELECT COUNT(1) FROM t2; ---error ER_NO_SUCH_TABLE_IN_ENGINE +--error ER_TABLE_CORRUPT SELECT COUNT(1) FROM t2,t1 where t2.a = t1.a; --error ER_TABLE_CORRUPT SELECT COUNT(1) FROM t1 where b = 'ab'; diff --git a/mysql-test/suite/encryption/t/innodb-redo-nokeys.test b/mysql-test/suite/encryption/t/innodb-redo-nokeys.test index 22fcd75446e..87a9e7a146e 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/engines/funcs/r/tc_partition_analyze.result b/mysql-test/suite/engines/funcs/r/tc_partition_analyze.result index cd4a0294ba5..ae3305b3fc2 100644 --- a/mysql-test/suite/engines/funcs/r/tc_partition_analyze.result +++ b/mysql-test/suite/engines/funcs/r/tc_partition_analyze.result @@ -33,7 +33,6 @@ t1 CREATE TABLE `t1` ( PARTITION `p5` VALUES LESS THAN MAXVALUE ENGINE = ENGINE) ALTER TABLE t1 ANALYZE PARTITION p1,p2; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT * FROM t1 ORDER BY c1; c1 c2 diff --git a/mysql-test/suite/federated/federatedx_create_handlers.result b/mysql-test/suite/federated/federatedx_create_handlers.result index 112540cb0bb..17c6d7f7bc3 100644 --- a/mysql-test/suite/federated/federatedx_create_handlers.result +++ b/mysql-test/suite/federated/federatedx_create_handlers.result @@ -536,6 +536,23 @@ use federated; SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM t1 where id=3) dt3 WHERE id=2) dt2) dt; id name +PREPARE stmt FROM " +SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM t1 where id=3) dt3 + WHERE id=3) dt2) dt; +"; +EXECUTE stmt; +id name +3 xxx +EXECUTE stmt; +id name +3 xxx +DEALLOCATE PREPARE stmt; +EXPLAIN +SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM t1 where id=3) dt3 +WHERE id=3) dt2) dt; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL NULL NULL NULL NULL 5 Using where +4 PUSHED DERIVED NULL NULL NULL NULL NULL NULL NULL NULL connection slave; CREATE TABLE federated.t10 (a INT,b INT); CREATE TABLE federated.t11 (a INT, b INT); @@ -556,6 +573,54 @@ WHERE id=2) dt2) dt a b a b id name 1 1 NULL NULL NULL NULL 2 2 NULL NULL NULL NULL +# +# MDEV-31361: Second execution of PS for query with derived table +# +connection slave; +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +id int(20) NOT NULL, +name varchar(16) NOT NULL default '' +) +DEFAULT CHARSET=latin1; +INSERT INTO federated.t1 VALUES +(3,'xxx'), (7,'yyy'), (4,'xxx'), (1,'zzz'), (5,'yyy'); +connection master; +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +id int(20) NOT NULL, +name varchar(16) NOT NULL default '' +) +ENGINE="FEDERATED" DEFAULT CHARSET=latin1 +CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; +use federated; +SELECT * FROM +(SELECT * FROM +(SELECT * FROM +(SELECT * FROM t1 where id>3) dt3 +WHERE id>3) dt2 +) dt; +id name +7 yyy +4 xxx +5 yyy +PREPARE stmt FROM "SELECT * FROM +(SELECT * FROM +(SELECT * FROM +(SELECT * FROM t1 where id>3) dt3 +WHERE id>3) dt2 +) dt"; +EXECUTE stmt; +id name +7 yyy +4 xxx +5 yyy +EXECUTE stmt; +id name +7 yyy +4 xxx +5 yyy +DEALLOCATE PREPARE stmt; set global federated_pushdown=0; connection master; DROP TABLE IF EXISTS federated.t1; diff --git a/mysql-test/suite/federated/federatedx_create_handlers.test b/mysql-test/suite/federated/federatedx_create_handlers.test index a83d25bd32d..2f10c23b2ee 100644 --- a/mysql-test/suite/federated/federatedx_create_handlers.test +++ b/mysql-test/suite/federated/federatedx_create_handlers.test @@ -95,12 +95,9 @@ DEFAULT CHARSET=latin1; INSERT INTO federated.t3 VALUES ('yyy'), ('www'), ('yyy'), ('xxx'), ('www'), ('yyy'), ('www'); -#Enable after fix MDEV-31361 ---disable_ps2_protocol SELECT * FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t WHERE federated.t3.name=t.name; ---enable_ps2_protocol EXPLAIN SELECT * @@ -358,6 +355,18 @@ use federated; SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM t1 where id=3) dt3 WHERE id=2) dt2) dt; +PREPARE stmt FROM " +SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM t1 where id=3) dt3 + WHERE id=3) dt2) dt; +"; +EXECUTE stmt; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +EXPLAIN +SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM t1 where id=3) dt3 + WHERE id=3) dt2) dt; + connection slave; CREATE TABLE federated.t10 (a INT,b INT); CREATE TABLE federated.t11 (a INT, b INT); @@ -383,6 +392,52 @@ SELECT * FROM t10 LEFT JOIN WHERE id=2) dt2) dt ) ON t10.a=t11.a; +--echo # +--echo # MDEV-31361: Second execution of PS for query with derived table +--echo # + +connection slave; +DROP TABLE IF EXISTS federated.t1; + +CREATE TABLE federated.t1 ( + id int(20) NOT NULL, + name varchar(16) NOT NULL default '' +) +DEFAULT CHARSET=latin1; + +INSERT INTO federated.t1 VALUES + (3,'xxx'), (7,'yyy'), (4,'xxx'), (1,'zzz'), (5,'yyy'); + +connection master; +DROP TABLE IF EXISTS federated.t1; + +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval +CREATE TABLE federated.t1 ( + id int(20) NOT NULL, + name varchar(16) NOT NULL default '' +) +ENGINE="FEDERATED" DEFAULT CHARSET=latin1 +CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; + +use federated; + +let $q= +SELECT * FROM + (SELECT * FROM + (SELECT * FROM + (SELECT * FROM t1 where id>3) dt3 + WHERE id>3) dt2 + ) dt; + +eval $q; + +eval PREPARE stmt FROM "$q"; +EXECUTE stmt; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + + set global federated_pushdown=0; source include/federated_cleanup.inc; diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index d6b30bba6ff..2d8e5e6299d 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -17,7 +17,6 @@ galera_ssl_upgrade : [Warning] Failed to load slave replication state from table galera_parallel_simple : timeout related to wsrep_sync_wait galera_insert_bulk : MDEV-30536 no expected deadlock in galera_insert_bulk test galera_sequences : MDEV-32561 WSREP FSM failure: no such a transition REPLICATING -> COMMITTED -galera_shutdown_nonprim : MDEV-32635 galera_shutdown_nonprim: mysql_shutdown failed versioning_trx_id : MDEV-18590 : galera.versioning_trx_id: Test failure: mysqltest: Result content mismatch galera_concurrent_ctas : MDEV-32779 galera_concurrent_ctas: assertion in the galera::ReplicatorSMM::finish_cert() galera_as_slave_replay : MDEV-32780 galera_as_slave_replay: assertion in the wsrep::transaction::before_rollback() @@ -26,5 +25,4 @@ galera_sst_mysqldump_with_key : MDEV-32782 galera_sst_mysqldump_with_key test fa mdev-31285 : MDEV-25089 Assertion `error.len > 0' failed in galera::ReplicatorSMM::handle_apply_error() galera_var_ignore_apply_errors : MENT-1997 galera_var_ignore_apply_errors test freezes MW-402 : temporarily disabled at the request of Codership -MDEV-22232 : temporarily disabled at the request of Codership galera_desync_overlapped : MDEV-21538 galera_desync_overlapped MTR failed: Result content mismatch diff --git a/mysql-test/suite/galera/r/MDEV-22232.result b/mysql-test/suite/galera/r/MDEV-22232.result index a6a619458f0..79db271bc50 100644 --- a/mysql-test/suite/galera/r/MDEV-22232.result +++ b/mysql-test/suite/galera/r/MDEV-22232.result @@ -3,21 +3,21 @@ connection node_1; connect con1,127.0.0.1,root,,test,$NODE_MYPORT_1; --- CTAS with empty result set --- CREATE TABLE t1 (a INT) ENGINE=InnoDB; -SET DEBUG_SYNC = 'create_table_select_before_create SIGNAL may_alter WAIT_FOR bf_abort'; +SET DEBUG_SYNC = 'create_table_select_before_create SIGNAL may_run WAIT_FOR bf_abort'; CREATE TABLE t2 SELECT * FROM t1; connection node_1; -SET DEBUG_SYNC = 'now WAIT_FOR may_alter'; -ALTER TABLE t1 DROP FOREIGN KEY b, ALGORITHM=COPY; +SET DEBUG_SYNC = 'now WAIT_FOR may_run'; +TRUNCATE TABLE t1; connection con1; ERROR 70100: Query execution was interrupted SET DEBUG_SYNC = 'RESET'; --- CTAS with non-empty result set --- INSERT INTO t1 VALUES (10), (20), (30); -SET DEBUG_SYNC = 'create_table_select_before_create SIGNAL may_alter WAIT_FOR bf_abort'; +SET DEBUG_SYNC = 'create_table_select_before_create SIGNAL may_run WAIT_FOR bf_abort'; CREATE TABLE t2 SELECT * FROM t1; connection node_1; -SET DEBUG_SYNC = 'now WAIT_FOR may_alter'; -ALTER TABLE t1 DROP FOREIGN KEY b, ALGORITHM=COPY; +SET DEBUG_SYNC = 'now WAIT_FOR may_run'; +TRUNCATE TABLE t1; connection con1; ERROR 70100: Query execution was interrupted SET DEBUG_SYNC = 'RESET'; diff --git a/mysql-test/suite/galera/r/MDEV-24143.result b/mysql-test/suite/galera/r/MDEV-24143.result index 860d8a35834..879e7d9c32c 100644 --- a/mysql-test/suite/galera/r/MDEV-24143.result +++ b/mysql-test/suite/galera/r/MDEV-24143.result @@ -14,7 +14,7 @@ c1 INSERT INTO t1 VALUES (4),(3),(1),(2); ERROR 40001: Deadlock found when trying to get lock; try restarting transaction CREATE TABLE t1 (pk INT PRIMARY KEY, b INT) ENGINE=SEQUENCE; -ERROR 42S01: Table 't1' already exists +ERROR 42000: This version of MariaDB doesn't yet support 'non-InnoDB sequences in Galera cluster' ALTER TABLE t1 DROP COLUMN c2; ERROR 42000: Can't DROP COLUMN `c2`; check that it exists SELECT get_lock ('test', 1.5); diff --git a/mysql-test/suite/galera/r/MDEV-25731.result b/mysql-test/suite/galera/r/MDEV-25731.result new file mode 100644 index 00000000000..92e1704e658 --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-25731.result @@ -0,0 +1,38 @@ +connection node_2; +connection node_1; +connection node_1; +SET GLOBAL wsrep_load_data_splitting=ON; +Warnings: +Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release +SET GLOBAL wsrep_replicate_myisam=ON; +Warnings: +Warning 1287 '@@wsrep_replicate_myisam' is deprecated and will be removed in a future release. Please use '@@wsrep_mode=REPLICATE_MYISAM' instead +CREATE TABLE t1 (c1 int) ENGINE=MYISAM; +LOAD DATA INFILE '../../std_data/mdev-25731.dat' IGNORE INTO TABLE t1 LINES TERMINATED BY '\n'; +Warnings: +Warning 1235 wsrep_load_data_splitting for other than InnoDB tables +SELECT COUNT(*) AS EXPECT_6 FROM t1; +EXPECT_6 +6 +connection node_2; +SELECT COUNT(*) AS EXPECT_6 FROM t1; +EXPECT_6 +6 +connection node_1; +ALTER TABLE t1 ENGINE=InnoDB; +LOAD DATA INFILE '../../std_data/mdev-25731.dat' IGNORE INTO TABLE t1 LINES TERMINATED BY '\n'; +SELECT COUNT(*) AS EXPECT_12 FROM t1; +EXPECT_12 +12 +connection node_2; +SELECT COUNT(*) AS EXPECT_12 FROM t1; +EXPECT_12 +12 +connection node_1; +DROP TABLE t1; +SET GLOBAL wsrep_load_data_splitting=OFF; +Warnings: +Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release +SET GLOBAL wsrep_replicate_myisam=OFF; +Warnings: +Warning 1287 '@@wsrep_replicate_myisam' is deprecated and will be removed in a future release. Please use '@@wsrep_mode=REPLICATE_MYISAM' instead diff --git a/mysql-test/suite/galera/r/MW-336.result b/mysql-test/suite/galera/r/MW-336.result index 8996b85c77c..e0cb1ee0464 100644 --- a/mysql-test/suite/galera/r/MW-336.result +++ b/mysql-test/suite/galera/r/MW-336.result @@ -1,7 +1,8 @@ connection node_2; connection node_1; connection node_1; -CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; +SET @wsrep_slave_threads_orig = @@wsrep_slave_threads; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) Engine=InnoDB; SET GLOBAL wsrep_slave_threads = 10; # Set slave threads to 10 step 1 SELECT VARIABLE_VALUE AS EXPECT_10 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_applier_thread_count'; @@ -9,7 +10,7 @@ EXPECT_10 10 SET GLOBAL wsrep_slave_threads = 1; connection node_2; -INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (NULL); connection node_1; # Wait until one of the appliers has exited SELECT VARIABLE_VALUE AS EXPECT_9 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_applier_thread_count'; @@ -27,33 +28,14 @@ EXPECT_20 20 SET GLOBAL wsrep_slave_threads = 1; connection node_2; -INSERT INTO t1 VALUES (1); -INSERT INTO t1 VALUES (2); -INSERT INTO t1 VALUES (3); -INSERT INTO t1 VALUES (4); -INSERT INTO t1 VALUES (5); -INSERT INTO t1 VALUES (6); -INSERT INTO t1 VALUES (7); -INSERT INTO t1 VALUES (8); -INSERT INTO t1 VALUES (9); -INSERT INTO t1 VALUES (10); -INSERT INTO t1 VALUES (11); -INSERT INTO t1 VALUES (12); -INSERT INTO t1 VALUES (13); -INSERT INTO t1 VALUES (14); -INSERT INTO t1 VALUES (16); -INSERT INTO t1 VALUES (17); -INSERT INTO t1 VALUES (18); -INSERT INTO t1 VALUES (19); -INSERT INTO t1 VALUES (20); connection node_1; # Wait until 19 of the appliers has exited SELECT VARIABLE_VALUE AS EXPECT_1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_applier_thread_count'; EXPECT_1 1 -SELECT COUNT(*) FROM t1; -COUNT(*) -20 +SELECT COUNT(*) AS EXPECT_51 FROM t1; +EXPECT_51 +51 SET GLOBAL wsrep_slave_threads = 10; # Set slave threads to 10 step 3 SELECT VARIABLE_VALUE AS EXPECT_10 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_applier_thread_count'; @@ -62,22 +44,12 @@ EXPECT_10 connection node_1; SET GLOBAL wsrep_slave_threads = 1; connection node_2; -INSERT INTO t1 VALUES (21); -INSERT INTO t1 VALUES (22); -INSERT INTO t1 VALUES (23); -INSERT INTO t1 VALUES (24); -INSERT INTO t1 VALUES (25); -INSERT INTO t1 VALUES (26); -INSERT INTO t1 VALUES (27); -INSERT INTO t1 VALUES (28); -INSERT INTO t1 VALUES (29); -INSERT INTO t1 VALUES (30); connection node_1; # Wait until slave threads back to 1 SELECT VARIABLE_VALUE AS EXPECT_1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_applier_thread_count'; EXPECT_1 1 -SELECT COUNT(*) FROM t1; -COUNT(*) -30 +SELECT COUNT(*) AS EXPECT_101 FROM t1; +EXPECT_101 +101 DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_mdl_race.result b/mysql-test/suite/galera/r/galera_mdl_race.result index cf747ed8efb..a7f0bc8e672 100644 --- a/mysql-test/suite/galera/r/galera_mdl_race.result +++ b/mysql-test/suite/galera/r/galera_mdl_race.result @@ -1,44 +1,68 @@ connection node_2; connection node_1; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)) engine=innodb; CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)) engine=innodb; INSERT INTO t1 VALUES (1, 'a'); INSERT INTO t1 VALUES (2, 'a'); -connection node_1; SET AUTOCOMMIT=ON; START TRANSACTION; UPDATE t1 SET f2 = 'b' WHERE f1 = 1; connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; connection node_1a; +SET SESSION wsrep_sync_wait=0; LOCK TABLE t2 WRITE; connection node_1; -SET @@debug_dbug = "d,sync.wsrep_before_mdl_wait"; +SET DEBUG_SYNC= 'wsrep_before_mdl_wait SIGNAL before_mdl_wait WAIT_FOR mdl_wait_continue'; SELECT * FROM t2;; connection node_1a; +# Wait until select is blocked before MDL lock wait +SET DEBUG_SYNC= 'now WAIT_FOR before_mdl_wait'; +connection node_1a; SET @@debug_dbug = "d,sync.wsrep_after_BF_victim_lock"; connection node_2; UPDATE t1 SET f2 = 'c' WHERE f1 = 1; -connection node_1a; -SET @@debug_dbug = ""; -SET DEBUG_SYNC = "now SIGNAL signal.wsrep_before_mdl_wait"; +connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connection node_1b; +SET SESSION wsrep_sync_wait=0; +# Wait for conflicting update to block SET DEBUG_SYNC = "now SIGNAL signal.wsrep_after_BF_victim_lock"; +connect node_1c, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connection node_1c; +connection node_1a; +SET DEBUG_SYNC = "now SIGNAL BF_victim_continue"; UNLOCK TABLES; connection node_1; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction -SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'a'; -COUNT(*) = 1 +connection node_1; +SELECT COUNT(*) AS EXPECT_1 FROM t1 WHERE f2 = 'a'; +EXPECT_1 1 -SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; -COUNT(*) = 1 +SELECT COUNT(*) AS EXPECT_1 FROM t1 WHERE f2 = 'c'; +EXPECT_1 1 +SELECT * FROM t1; +f1 f2 +1 c +2 a connection node_2; -SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'a'; -COUNT(*) = 1 +SELECT COUNT(*) AS EXPECT_1 FROM t1 WHERE f2 = 'a'; +EXPECT_1 1 -SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; -COUNT(*) = 1 +SELECT COUNT(*) AS EXPECT_1 FROM t1 WHERE f2 = 'c'; +EXPECT_1 1 +SELECT * FROM t1; +f1 f2 +1 c +2 a DROP TABLE t1; DROP TABLE t2; connection node_1a; SET DEBUG_SYNC = "RESET"; +connection node_1b; +SET DEBUG_SYNC = "RESET"; +connection node_1; +disconnect node_1a; +disconnect node_1b; +disconnect node_1c; diff --git a/mysql-test/suite/galera/r/galera_myisam_autocommit.result b/mysql-test/suite/galera/r/galera_myisam_autocommit.result index b80af779430..23883ef3a2f 100644 --- a/mysql-test/suite/galera/r/galera_myisam_autocommit.result +++ b/mysql-test/suite/galera/r/galera_myisam_autocommit.result @@ -15,16 +15,37 @@ UPDATE t1 SET f1 = 9; UPDATE t2 SET f1 = 9 WHERE f1 = 1; DELETE FROM t1 WHERE f1 = 9; DELETE FROM t2 WHERE f1 = 9; -TRUNCATE TABLE t1; -TRUNCATE TABLE t1; +SELECT * FROM t1 ORDER BY f1; +f1 +SELECT * FROM t2 ORDER BY f1; +f1 +2 +3 +4 +5 +6 connection node_2; -SELECT COUNT(*) = 0 FROM t1; -COUNT(*) = 0 -1 -SELECT COUNT(*) = 0 FROM t2; -COUNT(*) = 0 -0 +SELECT * FROM t1 ORDER BY f1; +f1 +SELECT * FROM t2 ORDER BY f1; +f1 +2 +3 +4 +5 +6 +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +SELECT * FROM t1 ORDER BY f1; +f1 +SELECT * FROM t2 ORDER BY f1; +f1 +connection node_2; +SELECT * FROM t1 ORDER BY f1; +f1 +SELECT * FROM t2 ORDER BY f1; +f1 connection node_1; +SET GLOBAL wsrep_mode=DEFAULT; DROP TABLE t1; DROP TABLE t2; -SET GLOBAL wsrep_mode=DEFAULT; diff --git a/mysql-test/suite/galera/r/galera_sequence_engine.result b/mysql-test/suite/galera/r/galera_sequence_engine.result new file mode 100644 index 00000000000..93e6c46bd7a --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sequence_engine.result @@ -0,0 +1,12 @@ +connection node_2; +connection node_1; +SET GLOBAL wsrep_ignore_apply_errors=0; +SET SESSION AUTOCOMMIT=0; +SET SESSION max_error_count=0; +CREATE TABLE t0 (id GEOMETRY,parent_id GEOMETRY)ENGINE=SEQUENCE; +ERROR 42000: This version of MariaDB doesn't yet support 'non-InnoDB sequences in Galera cluster' +connection node_2; +SHOW CREATE TABLE t0; +ERROR 42S02: Table 'test.t0' doesn't exist +connection node_1; +SET GLOBAL wsrep_ignore_apply_errors=DEFAULT; diff --git a/mysql-test/suite/galera/r/galera_shutdown_nonprim.result b/mysql-test/suite/galera/r/galera_shutdown_nonprim.result index 8b7697432a3..d577eab9f1a 100644 --- a/mysql-test/suite/galera/r/galera_shutdown_nonprim.result +++ b/mysql-test/suite/galera/r/galera_shutdown_nonprim.result @@ -5,7 +5,12 @@ connection node_2; connection node_1; SET GLOBAL wsrep_provider_options = 'pc.weight=2'; connection node_2; -SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1'; SET SESSION wsrep_sync_wait = 0; +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1'; +connection node_1; +connection node_2; +SHOW STATUS LIKE 'wsrep_cluster_status'; +Variable_name Value +wsrep_cluster_status non-Primary connection node_1; SET GLOBAL wsrep_provider_options = 'pc.weight = 1'; diff --git a/mysql-test/suite/galera/r/mdev-22063.result b/mysql-test/suite/galera/r/mdev-22063.result new file mode 100644 index 00000000000..c594bc47b95 --- /dev/null +++ b/mysql-test/suite/galera/r/mdev-22063.result @@ -0,0 +1,243 @@ +connection node_2; +connection node_1; +# Case 1 CREATE SEQUENCE with no NOCACHE +CREATE SEQUENCE s ENGINE=InnoDB; +ERROR 42000: This version of MariaDB doesn't yet support 'CACHE without INCREMENT BY 0 in Galera cluster' +CREATE SEQUENCE s NOCACHE ENGINE=InnoDB; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +START TRANSACTION; +REPLACE INTO s VALUES (1,1,9223372036854775806,1,1,1000,0,0); +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize note Table does not support optimize, doing recreate + analyze instead +test.t1 optimize status OK +SELECT * FROM t1; +a +SELECT * FROM s; +next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count +1 1 9223372036854775806 1 1 1000 0 0 +connection node_2; +SELECT * FROM t1; +a +SELECT * FROM s; +next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count +1 1 9223372036854775806 1 1 1000 0 0 +connection node_1; +DROP TABLE t1; +DROP SEQUENCE s; +# Case 2 REPLACE INTO ... SELECT with error +CREATE TABLE t (id INT KEY,a YEAR,INDEX (id,a)) engine=innodb; +REPLACE INTO t (id,a)SELECT /*!99997 */ 1; +ERROR 21S01: Column count doesn't match value count at row 1 +REPLACE INTO t (id,a)SELECT /*!99997 */ 1,2; +SELECT * FROM t; +id a +1 2002 +CREATE TABLE t2 (id INT KEY,a YEAR,INDEX (id,a)) engine=myisam; +REPLACE INTO t2 (id,a)SELECT /*!99997 */ 1; +ERROR 21S01: Column count doesn't match value count at row 1 +REPLACE INTO t2 (id,a)SELECT /*!99997 */ 1,2; +Warnings: +Warning 138 Galera cluster does support consistency check only for InnoDB tables. +SELECT * FROM t2; +id a +1 2002 +CREATE TABLE t3 (id INT KEY,a YEAR,INDEX (id,a)) engine=aria; +REPLACE INTO t3 (id,a)SELECT /*!99997 */ 1; +ERROR 21S01: Column count doesn't match value count at row 1 +REPLACE INTO t3 (id,a)SELECT /*!99997 */ 1,2; +Warnings: +Warning 138 Galera cluster does support consistency check only for InnoDB tables. +SELECT * FROM t3; +id a +1 2002 +connection node_2; +SELECT * FROM t; +id a +1 2002 +SELECT * FROM t2; +id a +1 2002 +SELECT * FROM t3; +id a +1 2002 +connection node_1; +DROP TABLE t,t2,t3; +# Bigger REPLACE ... AS SELECT test +CREATE TABLE t1(id int not null primary key ,b int) ENGINE=InnoDB; +CREATE TABLE t2(id int not null primary key ,b int) ENGINE=MyISAM; +CREATE TABLE t3(id int not null primary key ,b int) ENGINE=Aria; +CREATE TABLE t4(id int not null primary key ,b int) ENGINE=InnoDB; +CREATE TABLE t5(id int not null primary key ,b int) ENGINE=InnoDB; +CREATE TABLE t6(id int not null primary key ,b int) ENGINE=InnoDB; +CREATE TABLE t7(id int not null primary key ,b int) ENGINE=MyISAM; +CREATE TABLE t8(id int not null primary key ,b int) ENGINE=Aria; +INSERT INTO t1(id) SELECT seq FROM seq_1_to_1000; +INSERT INTO t2(id) SELECT seq FROM seq_1_to_1000; +INSERT INTO t3(id) SELECT seq FROM seq_1_to_1000; +REPLACE INTO t4 SELECT * FROM t1; +REPLACE INTO t5 SELECT * FROM t2; +REPLACE INTO t6 SELECT * FROM t3; +ERROR HY000: Transactional commit not supported by involved engine(s) +REPLACE INTO t7 SELECT * FROM t2; +REPLACE INTO t8 SELECT * FROM t3; +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t2; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t3; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t4; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t5; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_0 FROM t6; +EXPECT_0 +0 +SELECT COUNT(*) AS EXPECT_1000 FROM t7; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t8; +EXPECT_1000 +1000 +connection node_2; +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t2; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t3; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t4; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t5; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_0 FROM t6; +EXPECT_0 +0 +SELECT COUNT(*) AS EXPECT_1000 FROM t7; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t8; +EXPECT_1000 +1000 +connection node_1; +DROP TABLE t1,t2,t3,t4,t5,t6,t7,t8; +# Bigger INSERT INTO ... SELECT test +CREATE TABLE t1(id int not null primary key ,b int) ENGINE=InnoDB; +CREATE TABLE t2(id int not null primary key ,b int) ENGINE=MyISAM; +CREATE TABLE t3(id int not null primary key ,b int) ENGINE=Aria; +CREATE TABLE t4(id int not null primary key ,b int) ENGINE=InnoDB; +CREATE TABLE t5(id int not null primary key ,b int) ENGINE=InnoDB; +CREATE TABLE t6(id int not null primary key ,b int) ENGINE=InnoDB; +CREATE TABLE t7(id int not null primary key ,b int) ENGINE=MyISAM; +CREATE TABLE t8(id int not null primary key ,b int) ENGINE=Aria; +INSERT INTO t1(id) SELECT seq FROM seq_1_to_1000; +INSERT INTO t2(id) SELECT seq FROM seq_1_to_1000; +INSERT INTO t3(id) SELECT seq FROM seq_1_to_1000; +INSERT INTO t4 SELECT * FROM t1; +INSERT INTO t5 SELECT * FROM t2; +INSERT INTO t6 SELECT * FROM t3; +ERROR HY000: Transactional commit not supported by involved engine(s) +INSERT INTO t7 SELECT * FROM t2; +INSERT INTO t8 SELECT * FROM t3; +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t2; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t3; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t4; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t5; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_0 FROM t6; +EXPECT_0 +0 +SELECT COUNT(*) AS EXPECT_1000 FROM t7; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t8; +EXPECT_1000 +1000 +connection node_2; +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t2; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t3; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t4; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t5; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_0 FROM t6; +EXPECT_0 +0 +SELECT COUNT(*) AS EXPECT_1000 FROM t7; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t8; +EXPECT_1000 +1000 +connection node_1; +DROP TABLE t1,t2,t3,t4,t5,t6,t7,t8; +CREATE TABLE t1(pk int not null primary key) engine=innodb; +INSERT INTO t1 values (1),(2),(3),(4); +CREATE VIEW view_t1 AS SELECT * FROM t1; +INSERT INTO view_t1 VALUES (5); +SELECT * FROM t1; +pk +1 +2 +3 +4 +5 +DROP TABLE t1; +DROP VIEW view_t1; +CREATE TABLE t1(pk int not null primary key) engine=myisam; +INSERT INTO t1 values (1),(2),(3),(4); +CREATE VIEW view_t1 AS SELECT * FROM t1; +INSERT INTO view_t1 VALUES (5); +SELECT * FROM t1; +pk +1 +2 +3 +4 +5 +DROP TABLE t1; +DROP VIEW view_t1; +CREATE TABLE t1(pk int not null primary key) engine=aria; +INSERT INTO t1 values (1),(2),(3),(4); +CREATE VIEW view_t1 AS SELECT * FROM t1; +INSERT INTO view_t1 VALUES (5); +SELECT * FROM t1; +pk +1 +2 +3 +4 +5 +DROP TABLE t1; +DROP VIEW view_t1; +SET GLOBAL wsrep_mode=DEFAULT; diff --git a/mysql-test/suite/galera/r/mdev-31285.result b/mysql-test/suite/galera/r/mdev-31285.result index 228f62fa305..58fcb385b1a 100644 --- a/mysql-test/suite/galera/r/mdev-31285.result +++ b/mysql-test/suite/galera/r/mdev-31285.result @@ -1,23 +1,8 @@ connection node_2; connection node_1; connection node_1; -connection node_2; -connection node_1; CREATE TABLE t ENGINE=InnoDB WITH SYSTEM VERSIONING AS SELECT 1 AS i; +ERROR 42000: This version of MariaDB doesn't yet support 'SYSTEM VERSIONING AS SELECT in Galera cluster' +connection node_2; SHOW CREATE TABLE t; -Table Create Table -t CREATE TABLE `t` ( - `i` int(1) NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci WITH SYSTEM VERSIONING -SELECT * from t; -i -1 -DROP TABLE IF EXISTS t; -COMMIT; -connection node_2; -SET SESSION wsrep_sync_wait=0; -Killing server ... -Starting server ... -connection node_2; -call mtr.add_suppression("WSREP: Event .*Write_rows_v1 apply failed:.*"); -call mtr.add_suppression("SREP: Failed to apply write set: gtid:.*"); +ERROR 42S02: Table 'test.t' doesn't exist diff --git a/mysql-test/suite/galera/r/rpl_galera_to_mariadb_clone_slave_using_mariadb-backup.result b/mysql-test/suite/galera/r/rpl_galera_to_mariadb_clone_slave_using_mariadb-backup.result new file mode 100644 index 00000000000..76c13fa7b89 --- /dev/null +++ b/mysql-test/suite/galera/r/rpl_galera_to_mariadb_clone_slave_using_mariadb-backup.result @@ -0,0 +1,211 @@ +connection node_2; +connection node_1; +# +# MDEV-33355 Add a Galera-2-node-to-MariaDB replication MTR test cloning the slave with mariadb-backup +# +connect master, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connect slave, 127.0.0.1, root, , test, $NODE_MYPORT_3; +START SLAVE; +include/wait_for_slave_to_start.inc +connection master; +connection slave; +############################################################## +### Initial block with some transactions +### Slave: Make sure replication is not using GTID +connection slave; +# Using_Gtid=No +### Master: Create and populate t1 +connection master; +CREATE TABLE t1(a TEXT) ENGINE=InnoDB; +START TRANSACTION; +INSERT INTO t1 VALUES ('tr#00:stmt#00 - slave run#0, before backup'); +INSERT INTO t1 VALUES ('tr#00:stmt#01 - slave run#0, before backup'); +INSERT INTO t1 VALUES ('tr#00:stmt#02 - slave run#0, before backup'); +COMMIT; +connection slave; +############################################################## +### Run the last transaction before mariadb-backup --backup +### Remember SHOW MASTER STATUS and @@gtid_binlog_pos +### before and after the transaction. +### Master: Rember MASTER STATUS and @@gtid_binlog_pos before tr#01 +connection master; +### Slave: Remember MASTER STATUS and @@gtid_binlog_pos before tr#01 +connection slave; +### Master: Run the actual last transaction before the backup +connection master; +START TRANSACTION; +INSERT INTO t1 VALUES ('tr#01:stmt#00 - slave run#0, before backup'); +INSERT INTO t1 VALUES ('tr#01:stmt#01 - slave run#0, before backup'); +INSERT INTO t1 VALUES ('tr#01:stmt#02 - slave run#0, before backup'); +COMMIT; +connection slave; +### Master: Remember MASTER STATUS and @@gtid_binlog_pos after tr#01 +connection master; +### Slave: Remember MASTER STATUS and @@gtid_binlog_pos after tr#01 +connection slave; +############################################################## +### Running `mariadb-backup --backup,--prepare` and checking +### that xtrabackup_slave_info and xtrabackup_binlog_info are OK +### Slave: Create a backup +### Slave: Prepare the backup +### Slave: xtrabackup files: +############################ xtrabackup_slave_info +CHANGE MASTER TO MASTER_LOG_FILE='master_after_tr01_show_master_status_file', MASTER_LOG_POS=master_after_tr01_show_master_status_position; +############################ xtrabackup_binlog_info +slave_after_tr01_show_master_status_file slave_after_tr01_show_master_status_position slave_after_tr01_gtid_binlog_pos +############################ +############################################################## +### Run more transactions after the backup: +### - while the slave is still running, then +### - while the slave is shut down +### Master: Run another transaction while the slave is still running +connection master; +START TRANSACTION; +INSERT INTO t1 VALUES ('tr#02:stmt#00 - slave run#0, after backup'); +INSERT INTO t1 VALUES ('tr#02:stmt#01 - slave run#0, after backup'); +INSERT INTO t1 VALUES ('tr#02:stmt@02 - slave run#0, after backup'); +COMMIT; +connection slave; +### Master: Remember MASTER STATUS and @@gtid_binlog_pos after tr#02 +connection master; +### Slave: Remember MASTER STATUS and @@gtid_binlog_pos after tr#02 +connection slave; +### Master: Checking SHOW BINLOG EVENTS +connection master; +SHOW BINLOG EVENTS IN 'master_after_tr01_show_master_status_file' FROM master_after_tr01_show_master_status_position LIMIT 0,1; +Log_name master_after_tr01_show_master_status_file +Pos master_after_tr01_show_master_status_position +Event_type Gtid +Server_id # +End_log_pos # +Info BEGIN GTID master_after_tr02_gtid_binlog_pos +SHOW BINLOG EVENTS IN 'master_after_tr01_show_master_status_file' FROM master_after_tr01_show_master_status_position LIMIT 1,1; +Log_name master_after_tr01_show_master_status_file +Pos # +Event_type Query_or_Annotate_rows +Server_id # +End_log_pos # +Info INSERT INTO t1 VALUES ('tr#02:stmt#00 - slave run#0, after backup') +### Slave: Checking SHOW BINLOG EVENTS +connection slave; +SHOW BINLOG EVENTS IN 'slave_after_tr01_show_master_status_file' FROM slave_after_tr01_show_master_status_position LIMIT 0,1; +Log_name slave_after_tr01_show_master_status_file +Pos # +Event_type Gtid +Server_id 1 +End_log_pos # +Info BEGIN GTID slave_after_tr02_gtid_binlog_pos +SHOW BINLOG EVENTS IN 'slave_after_tr01_show_master_status_file' FROM slave_after_tr01_show_master_status_position LIMIT 1,1; +Log_name slave_after_tr01_show_master_status_file +Pos # +Event_type Query_or_Annotate_rows +Server_id # +End_log_pos # +Info INSERT INTO t1 VALUES ('tr#02:stmt#00 - slave run#0, after backup') +### Slave: Stop replication +connection slave; +STOP SLAVE; +include/wait_for_slave_to_stop.inc +RESET SLAVE; +Warnings: +Note 4190 RESET SLAVE is implicitly changing the value of 'Using_Gtid' from 'No' to 'Slave_Pos' +### Slave: Shutdown the server +connection slave; +### Master: Run a transaction while the slave is shut down +connection master; +START TRANSACTION; +INSERT INTO t1 VALUES ('tr#03:stmt#00 - after slave run#0, slave is shut down, after backup'); +INSERT INTO t1 VALUES ('tr#03:stmt#01 - after slave run#0, slave is shut down, after backup'); +INSERT INTO t1 VALUES ('tr#03:stmt#02 - after slave run#0, slave is shut down, after backup'); +COMMIT; +############################################################## +### Emulate starting a new virgin slave +### Slave: Remove the data directory +### Slave: Copy back the backup +### Slave: Restart the server +connection slave; +# restart +### Slave: Display the restored data before START SLAVE +connection slave; +SELECT * FROM t1 ORDER BY a; +a +tr#00:stmt#00 - slave run#0, before backup +tr#00:stmt#01 - slave run#0, before backup +tr#00:stmt#02 - slave run#0, before backup +tr#01:stmt#00 - slave run#0, before backup +tr#01:stmt#01 - slave run#0, before backup +tr#01:stmt#02 - slave run#0, before backup +### Slave: Execute the CHANGE MASTER statement to set up the host and port +CHANGE MASTER '' TO MASTER_USER='root', MASTER_HOST='127.0.0.1', MASTER_PORT=###, MASTER_CONNECT_RETRY=1; +### Slave: Execute the CHANGE MASTER statement from xtrabackup_slave_info +CHANGE MASTER TO MASTER_LOG_FILE='master_after_tr01_show_master_status_file', MASTER_LOG_POS=master_after_tr01_show_master_status_position; +Warnings: +Note 4190 CHANGE MASTER TO is implicitly changing the value of 'Using_Gtid' from 'Slave_Pos' to 'No' +### Slave: Execute START SLAVE +include/start_slave.inc +### Master: Wait for the slave to apply all master events +connection master; +connection slave; +### Slave: Make sure replication is not using GTID after the slave restart +connection slave; +# Using_Gtid=No +### Slave: Display the restored data after START SLAVE +connection slave; +SELECT * FROM t1 ORDER BY a; +a +tr#00:stmt#00 - slave run#0, before backup +tr#00:stmt#01 - slave run#0, before backup +tr#00:stmt#02 - slave run#0, before backup +tr#01:stmt#00 - slave run#0, before backup +tr#01:stmt#01 - slave run#0, before backup +tr#01:stmt#02 - slave run#0, before backup +tr#02:stmt#00 - slave run#0, after backup +tr#02:stmt#01 - slave run#0, after backup +tr#02:stmt@02 - slave run#0, after backup +tr#03:stmt#00 - after slave run#0, slave is shut down, after backup +tr#03:stmt#01 - after slave run#0, slave is shut down, after backup +tr#03:stmt#02 - after slave run#0, slave is shut down, after backup +############################################################## +### Continue master transactions, check the new slave replicates well. +### Master: Run a transaction after restarting replication +connection master; +START TRANSACTION; +INSERT INTO t1 VALUES ('tr#04:stmt#00 - slave run#1'); +INSERT INTO t1 VALUES ('tr#04:stmt#01 - slave run#1'); +INSERT INTO t1 VALUES ('tr#04:stmt#02 - slave run#1'); +COMMIT; +connection slave; +### Slave: Display the restored data + new transactions +connection slave; +SELECT * FROM t1 ORDER BY a; +a +tr#00:stmt#00 - slave run#0, before backup +tr#00:stmt#01 - slave run#0, before backup +tr#00:stmt#02 - slave run#0, before backup +tr#01:stmt#00 - slave run#0, before backup +tr#01:stmt#01 - slave run#0, before backup +tr#01:stmt#02 - slave run#0, before backup +tr#02:stmt#00 - slave run#0, after backup +tr#02:stmt#01 - slave run#0, after backup +tr#02:stmt@02 - slave run#0, after backup +tr#03:stmt#00 - after slave run#0, slave is shut down, after backup +tr#03:stmt#01 - after slave run#0, slave is shut down, after backup +tr#03:stmt#02 - after slave run#0, slave is shut down, after backup +tr#04:stmt#00 - slave run#1 +tr#04:stmt#01 - slave run#1 +tr#04:stmt#02 - slave run#1 +############################################################## +### Cleanup +### Removing the backup directory +connection master; +DROP TABLE t1; +connection slave; +STOP SLAVE; +include/wait_for_slave_to_stop.inc +RESET SLAVE ALL; +Warnings: +Note 4190 RESET SLAVE is implicitly changing the value of 'Using_Gtid' from 'No' to 'Slave_Pos' +connection master; +set global wsrep_on=OFF; +RESET MASTER; +set global wsrep_on=ON; diff --git a/mysql-test/suite/galera/t/MDEV-22232.test b/mysql-test/suite/galera/t/MDEV-22232.test index dbd9ed1e9c7..087d6417b01 100644 --- a/mysql-test/suite/galera/t/MDEV-22232.test +++ b/mysql-test/suite/galera/t/MDEV-22232.test @@ -18,19 +18,16 @@ CREATE TABLE t1 (a INT) ENGINE=InnoDB; # Run CTAS until the resulting table gets created, -# then it gets BF aborted by ALTER. -SET DEBUG_SYNC = 'create_table_select_before_create SIGNAL may_alter WAIT_FOR bf_abort'; +# then it gets BF aborted by other DDL. +SET DEBUG_SYNC = 'create_table_select_before_create SIGNAL may_run WAIT_FOR bf_abort'; --send CREATE TABLE t2 SELECT * FROM t1; # Wait for CTAS to reach the table create point, -# start executing ALTER and BF abort CTAS. +# start executing other DDL and BF abort CTAS. --connection node_1 -SET DEBUG_SYNC = 'now WAIT_FOR may_alter'; ---disable_result_log ---error ER_CANT_DROP_FIELD_OR_KEY -ALTER TABLE t1 DROP FOREIGN KEY b, ALGORITHM=COPY; ---enable_result_log +SET DEBUG_SYNC = 'now WAIT_FOR may_run'; +TRUNCATE TABLE t1; --connection con1 # CTAS gets BF aborted. @@ -46,19 +43,16 @@ SET DEBUG_SYNC = 'RESET'; INSERT INTO t1 VALUES (10), (20), (30); # Run CTAS until the resulting table gets created, -# then it gets BF aborted by ALTER. -SET DEBUG_SYNC = 'create_table_select_before_create SIGNAL may_alter WAIT_FOR bf_abort'; +# then it gets BF aborted by other DDL. +SET DEBUG_SYNC = 'create_table_select_before_create SIGNAL may_run WAIT_FOR bf_abort'; --send CREATE TABLE t2 SELECT * FROM t1; # Wait for CTAS to reach the table create point, -# start executing ALTER and BF abort CTAS. +# start executing other DDL and BF abort CTAS. --connection node_1 -SET DEBUG_SYNC = 'now WAIT_FOR may_alter'; ---disable_result_log ---error ER_ERROR_ON_RENAME -ALTER TABLE t1 DROP FOREIGN KEY b, ALGORITHM=COPY; ---enable_result_log +SET DEBUG_SYNC = 'now WAIT_FOR may_run'; +TRUNCATE TABLE t1; --connection con1 # CTAS gets BF aborted. diff --git a/mysql-test/suite/galera/t/MDEV-24143.test b/mysql-test/suite/galera/t/MDEV-24143.test index e58f147cb7c..3aecac8cb07 100644 --- a/mysql-test/suite/galera/t/MDEV-24143.test +++ b/mysql-test/suite/galera/t/MDEV-24143.test @@ -11,7 +11,11 @@ SET SESSION autocommit=0; SELECT * FROM t1 WHERE c1 <=0 ORDER BY c1 DESC; --error ER_LOCK_DEADLOCK INSERT INTO t1 VALUES (4),(3),(1),(2); ---error ER_TABLE_EXISTS_ERROR +# +# This is because support for CREATE TABLE ENGINE=SEQUENCE +# is done before we check does table exists already. +# +--error ER_NOT_SUPPORTED_YET CREATE TABLE t1 (pk INT PRIMARY KEY, b INT) ENGINE=SEQUENCE; --error ER_CANT_DROP_FIELD_OR_KEY ALTER TABLE t1 DROP COLUMN c2; diff --git a/mysql-test/suite/galera/t/MDEV-25731.test b/mysql-test/suite/galera/t/MDEV-25731.test new file mode 100644 index 00000000000..c26fad2fa6a --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-25731.test @@ -0,0 +1,27 @@ +--source include/galera_cluster.inc +--source include/have_aria.inc + +--connection node_1 +SET GLOBAL wsrep_load_data_splitting=ON; +SET GLOBAL wsrep_replicate_myisam=ON; +CREATE TABLE t1 (c1 int) ENGINE=MYISAM; +LOAD DATA INFILE '../../std_data/mdev-25731.dat' IGNORE INTO TABLE t1 LINES TERMINATED BY '\n'; +SELECT COUNT(*) AS EXPECT_6 FROM t1; + +--connection node_2 +SELECT COUNT(*) AS EXPECT_6 FROM t1; + +--connection node_1 +ALTER TABLE t1 ENGINE=InnoDB; +LOAD DATA INFILE '../../std_data/mdev-25731.dat' IGNORE INTO TABLE t1 LINES TERMINATED BY '\n'; +SELECT COUNT(*) AS EXPECT_12 FROM t1; + +--connection node_2 +SELECT COUNT(*) AS EXPECT_12 FROM t1; + +--connection node_1 +DROP TABLE t1; +SET GLOBAL wsrep_load_data_splitting=OFF; +SET GLOBAL wsrep_replicate_myisam=OFF; + + diff --git a/mysql-test/suite/galera/t/MW-336.cnf b/mysql-test/suite/galera/t/MW-336.cnf index e68f891792c..da97be5f86d 100644 --- a/mysql-test/suite/galera/t/MW-336.cnf +++ b/mysql-test/suite/galera/t/MW-336.cnf @@ -2,6 +2,8 @@ [mysqld.1] wsrep-debug=SERVER +loose-wsrep-mw-336=1 [mysqld.2] wsrep-debug=SERVER +loose-wsrep-mw-336=2 diff --git a/mysql-test/suite/galera/t/MW-336.test b/mysql-test/suite/galera/t/MW-336.test index 83943c7d8ea..29a70978e5e 100644 --- a/mysql-test/suite/galera/t/MW-336.test +++ b/mysql-test/suite/galera/t/MW-336.test @@ -3,11 +3,12 @@ # --source include/galera_cluster.inc ---source include/have_innodb.inc --source include/force_restart.inc +--source include/have_sequence.inc --connection node_1 -CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; +SET @wsrep_slave_threads_orig = @@wsrep_slave_threads; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) Engine=InnoDB; SET GLOBAL wsrep_slave_threads = 10; @@ -22,7 +23,7 @@ SELECT VARIABLE_VALUE AS EXPECT_10 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE V SET GLOBAL wsrep_slave_threads = 1; --connection node_2 -INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (NULL); --connection node_1 --echo # Wait until one of the appliers has exited @@ -54,27 +55,19 @@ SELECT VARIABLE_VALUE AS EXPECT_20 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE V SET GLOBAL wsrep_slave_threads = 1; --connection node_2 -INSERT INTO t1 VALUES (1); -INSERT INTO t1 VALUES (2); -INSERT INTO t1 VALUES (3); -INSERT INTO t1 VALUES (4); -INSERT INTO t1 VALUES (5); -INSERT INTO t1 VALUES (6); -INSERT INTO t1 VALUES (7); -INSERT INTO t1 VALUES (8); -INSERT INTO t1 VALUES (9); -INSERT INTO t1 VALUES (10); -INSERT INTO t1 VALUES (11); -INSERT INTO t1 VALUES (12); -INSERT INTO t1 VALUES (13); -INSERT INTO t1 VALUES (14); -INSERT INTO t1 VALUES (16); -INSERT INTO t1 VALUES (17); -INSERT INTO t1 VALUES (18); -INSERT INTO t1 VALUES (19); -INSERT INTO t1 VALUES (20); +--disable_query_log +let $c = 50; +while ($c) { +INSERT INTO t1 VALUES(NULL); COMMIT; +dec $c; +} +--enable_query_log --connection node_1 +--let $wait_condition = SELECT COUNT(*) = 51 FROM t1; +--let $wait_condition_on_error_output = SELECT COUNT(*) FROM t1; +--source include/wait_condition_with_debug.inc + --echo # Wait until 19 of the appliers has exited --let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_applier_thread_count'; --let $wait_condition_on_error_output = SELECT COUNT(*), 1 as EXPECTED_VALUE FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE = 'wsrep applier idle'; show processlist @@ -82,7 +75,7 @@ INSERT INTO t1 VALUES (20); SELECT VARIABLE_VALUE AS EXPECT_1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_applier_thread_count'; -SELECT COUNT(*) FROM t1; +SELECT COUNT(*) AS EXPECT_51 FROM t1; SET GLOBAL wsrep_slave_threads = 10; --echo # Set slave threads to 10 step 3 @@ -96,16 +89,13 @@ SELECT VARIABLE_VALUE AS EXPECT_10 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE V SET GLOBAL wsrep_slave_threads = 1; --connection node_2 -INSERT INTO t1 VALUES (21); -INSERT INTO t1 VALUES (22); -INSERT INTO t1 VALUES (23); -INSERT INTO t1 VALUES (24); -INSERT INTO t1 VALUES (25); -INSERT INTO t1 VALUES (26); -INSERT INTO t1 VALUES (27); -INSERT INTO t1 VALUES (28); -INSERT INTO t1 VALUES (29); -INSERT INTO t1 VALUES (30); +--disable_query_log +let $c = 50; +while ($c) { +INSERT INTO t1 VALUES(NULL); COMMIT; +dec $c; +} +--enable_query_log --connection node_1 --echo # Wait until slave threads back to 1 @@ -115,6 +105,10 @@ INSERT INTO t1 VALUES (30); SELECT VARIABLE_VALUE AS EXPECT_1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_applier_thread_count'; -SELECT COUNT(*) FROM t1; +SELECT COUNT(*) AS EXPECT_101 FROM t1; DROP TABLE t1; + +--disable_query_log +SET GLOBAL wsrep_slave_threads = @wsrep_slave_threads_orig; +--enable_query_log diff --git a/mysql-test/suite/galera/t/galera_mdl_race.test b/mysql-test/suite/galera/t/galera_mdl_race.test index ad6770f9991..3341a3792f1 100644 --- a/mysql-test/suite/galera/t/galera_mdl_race.test +++ b/mysql-test/suite/galera/t/galera_mdl_race.test @@ -3,70 +3,92 @@ # --source include/galera_cluster.inc +--source include/have_debug.inc --source include/have_debug_sync.inc +--connection node_1 CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)) engine=innodb; CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)) engine=innodb; INSERT INTO t1 VALUES (1, 'a'); INSERT INTO t1 VALUES (2, 'a'); ---connection node_1 SET AUTOCOMMIT=ON; START TRANSACTION; - UPDATE t1 SET f2 = 'b' WHERE f1 = 1; # block access to t2 --connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 --connection node_1a +SET SESSION wsrep_sync_wait=0; +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2' +--let $wait_condition_on_error_output = SELECT * FROM INFORMATION_SCHEMA.TABLES +--source include/wait_condition_with_debug.inc LOCK TABLE t2 WRITE; -# Block before MLD lock wait +# Block before MDL lock wait --connection node_1 - SET @@debug_dbug = "d,sync.wsrep_before_mdl_wait"; +SET DEBUG_SYNC= 'wsrep_before_mdl_wait SIGNAL before_mdl_wait WAIT_FOR mdl_wait_continue'; --send SELECT * FROM t2; -# Wait for SELECT to be blocked --connection node_1a -#--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIS WHERE STATE = 'System lock'; -#--source include/wait_condition.inc -#--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'init' AND INFO = 'COMMIT'; -#--source include/wait_condition.inc +--echo # Wait until select is blocked before MDL lock wait +SET DEBUG_SYNC= 'now WAIT_FOR before_mdl_wait'; # block applier to wait after BF victim is locked +--connection node_1a SET @@debug_dbug = "d,sync.wsrep_after_BF_victim_lock"; # Issue a conflicting update on node #2 --connection node_2 UPDATE t1 SET f2 = 'c' WHERE f1 = 1; -# Unblock the SELECT, to enter wsrep_thd_is_BF ---connection node_1a -SET @@debug_dbug = ""; -SET DEBUG_SYNC = "now SIGNAL signal.wsrep_before_mdl_wait"; +--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1b +SET SESSION wsrep_sync_wait=0; +--echo # Wait for conflicting update to block +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Update_rows_log_event:%'; +--source include/wait_condition.inc -# unblock applier to try to BF the SELECT +# Unblock the SELECT, to enter wsrep_thd_is_BF SET DEBUG_SYNC = "now SIGNAL signal.wsrep_after_BF_victim_lock"; +--connect node_1c, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1c +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Update_rows_log_event:%'; +--source include/wait_condition.inc + +--connection node_1a +# unblock applier to try to BF the SELECT +SET DEBUG_SYNC = "now SIGNAL BF_victim_continue"; + # table lock is not needed anymore UNLOCK TABLES; -# SELECT succeeds +# SELECT returns deadlock --connection node_1 - --error ER_LOCK_DEADLOCK --reap -SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'a'; -SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; +--connection node_1 +SELECT COUNT(*) AS EXPECT_1 FROM t1 WHERE f2 = 'a'; +SELECT COUNT(*) AS EXPECT_1 FROM t1 WHERE f2 = 'c'; +SELECT * FROM t1; --connection node_2 -SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'a'; -SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; +SELECT COUNT(*) AS EXPECT_1 FROM t1 WHERE f2 = 'a'; +SELECT COUNT(*) AS EXPECT_1 FROM t1 WHERE f2 = 'c'; +SELECT * FROM t1; DROP TABLE t1; DROP TABLE t2; --connection node_1a SET DEBUG_SYNC = "RESET"; +--connection node_1b +SET DEBUG_SYNC = "RESET"; + +--connection node_1 +--disconnect node_1a +--disconnect node_1b +--disconnect node_1c diff --git a/mysql-test/suite/galera/t/galera_myisam_autocommit.test b/mysql-test/suite/galera/t/galera_myisam_autocommit.test index 3452a06a16c..0612aabb233 100644 --- a/mysql-test/suite/galera/t/galera_myisam_autocommit.test +++ b/mysql-test/suite/galera/t/galera_myisam_autocommit.test @@ -2,22 +2,24 @@ --source include/have_innodb.inc # -# This tests simple autocommit replication of MyISAM tables. No updates arrive on the slave. +# This tests simple autocommit replication of MyISAM tables. # -# Without a PK - SET GLOBAL wsrep_mode=REPLICATE_MYISAM; +# Without a PK + CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM; INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (2), (3); +# This is TOI INSERT INTO t1 SELECT 4 FROM DUAL UNION ALL SELECT 5 FROM DUAL; CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=MyISAM; INSERT INTO t2 VALUES (1); INSERT INTO t2 VALUES (2), (3); +# This is TOI INSERT INTO t2 SELECT 4 FROM DUAL UNION ALL SELECT 5 FROM DUAL; # Error @@ -34,16 +36,26 @@ UPDATE t2 SET f1 = 9 WHERE f1 = 1; DELETE FROM t1 WHERE f1 = 9; DELETE FROM t2 WHERE f1 = 9; +SELECT * FROM t1 ORDER BY f1; +SELECT * FROM t2 ORDER BY f1; + +--connection node_2 +SELECT * FROM t1 ORDER BY f1; +SELECT * FROM t2 ORDER BY f1; + # TRUNCATE TRUNCATE TABLE t1; -TRUNCATE TABLE t1; +TRUNCATE TABLE t2; + +SELECT * FROM t1 ORDER BY f1; +SELECT * FROM t2 ORDER BY f1; --connection node_2 -SELECT COUNT(*) = 0 FROM t1; -SELECT COUNT(*) = 0 FROM t2; +SELECT * FROM t1 ORDER BY f1; +SELECT * FROM t2 ORDER BY f1; --connection node_1 +SET GLOBAL wsrep_mode=DEFAULT; DROP TABLE t1; DROP TABLE t2; -SET GLOBAL wsrep_mode=DEFAULT; diff --git a/mysql-test/suite/galera/t/galera_sequence_engine.test b/mysql-test/suite/galera/t/galera_sequence_engine.test new file mode 100644 index 00000000000..47107dcce84 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sequence_engine.test @@ -0,0 +1,16 @@ +--source include/galera_cluster.inc +--source include/have_sequence.inc + +SET GLOBAL wsrep_ignore_apply_errors=0; +SET SESSION AUTOCOMMIT=0; +SET SESSION max_error_count=0; +--error ER_NOT_SUPPORTED_YET +CREATE TABLE t0 (id GEOMETRY,parent_id GEOMETRY)ENGINE=SEQUENCE; + +--connection node_2 +--error ER_NO_SUCH_TABLE +SHOW CREATE TABLE t0; + +--connection node_1 +SET GLOBAL wsrep_ignore_apply_errors=DEFAULT; + diff --git a/mysql-test/suite/galera/t/galera_shutdown_nonprim.test b/mysql-test/suite/galera/t/galera_shutdown_nonprim.test index cf7018cd751..d1a1c91456b 100644 --- a/mysql-test/suite/galera/t/galera_shutdown_nonprim.test +++ b/mysql-test/suite/galera/t/galera_shutdown_nonprim.test @@ -16,21 +16,27 @@ SET GLOBAL wsrep_provider_options = 'pc.weight=2'; --connection node_2 # Isolate node_2 from the group and wait until wsrep_ready becomes OFF. -SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1'; SET SESSION wsrep_sync_wait = 0; ---let $wait_condition = SELECT VARIABLE_VALUE = 'OFF' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready' ---source include/wait_condition.inc - -# Verify that graceful shutdown succeeds. ---source include/shutdown_mysqld.inc ---source include/start_mysqld.inc - ---let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; ---source include/wait_condition.inc +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1'; --connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 'OFF' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready' +--source include/wait_condition.inc +SHOW STATUS LIKE 'wsrep_cluster_status'; +# Verify that graceful shutdown succeeds. +--source include/shutdown_mysqld.inc + +--source include/start_mysqld.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; --source include/wait_condition.inc # Restore original settings. SET GLOBAL wsrep_provider_options = 'pc.weight = 1'; + --source include/auto_increment_offset_restore.inc diff --git a/mysql-test/suite/galera/t/mdev-22063.test b/mysql-test/suite/galera/t/mdev-22063.test new file mode 100644 index 00000000000..6a8f1ffa6ce --- /dev/null +++ b/mysql-test/suite/galera/t/mdev-22063.test @@ -0,0 +1,188 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_log_bin.inc +--source include/have_sequence.inc +--source include/have_aria.inc + +--echo # Case 1 CREATE SEQUENCE with no NOCACHE +--error ER_NOT_SUPPORTED_YET +CREATE SEQUENCE s ENGINE=InnoDB; +CREATE SEQUENCE s NOCACHE ENGINE=InnoDB; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +START TRANSACTION; +REPLACE INTO s VALUES (1,1,9223372036854775806,1,1,1000,0,0); +OPTIMIZE TABLE t1; +SELECT * FROM t1; +SELECT * FROM s; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1' +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 's' +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 1 FROM test.s; +--source include/wait_condition.inc + +SELECT * FROM t1; +SELECT * FROM s; + +--connection node_1 +DROP TABLE t1; +DROP SEQUENCE s; + +--echo # Case 2 REPLACE INTO ... SELECT with error +CREATE TABLE t (id INT KEY,a YEAR,INDEX (id,a)) engine=innodb; +--error ER_WRONG_VALUE_COUNT_ON_ROW +REPLACE INTO t (id,a)SELECT /*!99997 */ 1; +REPLACE INTO t (id,a)SELECT /*!99997 */ 1,2; +SELECT * FROM t; + +CREATE TABLE t2 (id INT KEY,a YEAR,INDEX (id,a)) engine=myisam; +--error ER_WRONG_VALUE_COUNT_ON_ROW +REPLACE INTO t2 (id,a)SELECT /*!99997 */ 1; +REPLACE INTO t2 (id,a)SELECT /*!99997 */ 1,2; +SELECT * FROM t2; + +CREATE TABLE t3 (id INT KEY,a YEAR,INDEX (id,a)) engine=aria; +--error ER_WRONG_VALUE_COUNT_ON_ROW +REPLACE INTO t3 (id,a)SELECT /*!99997 */ 1; +REPLACE INTO t3 (id,a)SELECT /*!99997 */ 1,2; +SELECT * FROM t3; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't3' +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 1 FROM test.t3; +--source include/wait_condition.inc + +SELECT * FROM t; +SELECT * FROM t2; +SELECT * FROM t3; + +--connection node_1 +DROP TABLE t,t2,t3; + +--echo # Bigger REPLACE ... AS SELECT test + +CREATE TABLE t1(id int not null primary key ,b int) ENGINE=InnoDB; +CREATE TABLE t2(id int not null primary key ,b int) ENGINE=MyISAM; +CREATE TABLE t3(id int not null primary key ,b int) ENGINE=Aria; +CREATE TABLE t4(id int not null primary key ,b int) ENGINE=InnoDB; +CREATE TABLE t5(id int not null primary key ,b int) ENGINE=InnoDB; +CREATE TABLE t6(id int not null primary key ,b int) ENGINE=InnoDB; +CREATE TABLE t7(id int not null primary key ,b int) ENGINE=MyISAM; +CREATE TABLE t8(id int not null primary key ,b int) ENGINE=Aria; + +INSERT INTO t1(id) SELECT seq FROM seq_1_to_1000; +INSERT INTO t2(id) SELECT seq FROM seq_1_to_1000; +INSERT INTO t3(id) SELECT seq FROM seq_1_to_1000; + +REPLACE INTO t4 SELECT * FROM t1; +REPLACE INTO t5 SELECT * FROM t2; +# For some reason Aria storage engine does register_ha +--error ER_ERROR_DURING_COMMIT +REPLACE INTO t6 SELECT * FROM t3; +REPLACE INTO t7 SELECT * FROM t2; +REPLACE INTO t8 SELECT * FROM t3; + +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +SELECT COUNT(*) AS EXPECT_1000 FROM t2; +SELECT COUNT(*) AS EXPECT_1000 FROM t3; +SELECT COUNT(*) AS EXPECT_1000 FROM t4; +SELECT COUNT(*) AS EXPECT_1000 FROM t5; +SELECT COUNT(*) AS EXPECT_0 FROM t6; +SELECT COUNT(*) AS EXPECT_1000 FROM t7; +SELECT COUNT(*) AS EXPECT_1000 FROM t8; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 8 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME LIKE 't_' +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 1000 FROM test.t8; +--source include/wait_condition.inc + +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +SELECT COUNT(*) AS EXPECT_1000 FROM t2; +SELECT COUNT(*) AS EXPECT_1000 FROM t3; +SELECT COUNT(*) AS EXPECT_1000 FROM t4; +SELECT COUNT(*) AS EXPECT_1000 FROM t5; +SELECT COUNT(*) AS EXPECT_0 FROM t6; +SELECT COUNT(*) AS EXPECT_1000 FROM t7; +SELECT COUNT(*) AS EXPECT_1000 FROM t8; + +--connection node_1 +DROP TABLE t1,t2,t3,t4,t5,t6,t7,t8; + +--echo # Bigger INSERT INTO ... SELECT test + +CREATE TABLE t1(id int not null primary key ,b int) ENGINE=InnoDB; +CREATE TABLE t2(id int not null primary key ,b int) ENGINE=MyISAM; +CREATE TABLE t3(id int not null primary key ,b int) ENGINE=Aria; +CREATE TABLE t4(id int not null primary key ,b int) ENGINE=InnoDB; +CREATE TABLE t5(id int not null primary key ,b int) ENGINE=InnoDB; +CREATE TABLE t6(id int not null primary key ,b int) ENGINE=InnoDB; +CREATE TABLE t7(id int not null primary key ,b int) ENGINE=MyISAM; +CREATE TABLE t8(id int not null primary key ,b int) ENGINE=Aria; + +INSERT INTO t1(id) SELECT seq FROM seq_1_to_1000; +INSERT INTO t2(id) SELECT seq FROM seq_1_to_1000; +INSERT INTO t3(id) SELECT seq FROM seq_1_to_1000; + +INSERT INTO t4 SELECT * FROM t1; +INSERT INTO t5 SELECT * FROM t2; +# For some reason Aria storage engine does register_ha +--error ER_ERROR_DURING_COMMIT +INSERT INTO t6 SELECT * FROM t3; +INSERT INTO t7 SELECT * FROM t2; +INSERT INTO t8 SELECT * FROM t3; + +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +SELECT COUNT(*) AS EXPECT_1000 FROM t2; +SELECT COUNT(*) AS EXPECT_1000 FROM t3; +SELECT COUNT(*) AS EXPECT_1000 FROM t4; +SELECT COUNT(*) AS EXPECT_1000 FROM t5; +SELECT COUNT(*) AS EXPECT_0 FROM t6; +SELECT COUNT(*) AS EXPECT_1000 FROM t7; +SELECT COUNT(*) AS EXPECT_1000 FROM t8; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 8 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME LIKE 't_' +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 1000 FROM test.t8; +--source include/wait_condition.inc + +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +SELECT COUNT(*) AS EXPECT_1000 FROM t2; +SELECT COUNT(*) AS EXPECT_1000 FROM t3; +SELECT COUNT(*) AS EXPECT_1000 FROM t4; +SELECT COUNT(*) AS EXPECT_1000 FROM t5; +SELECT COUNT(*) AS EXPECT_0 FROM t6; +SELECT COUNT(*) AS EXPECT_1000 FROM t7; +SELECT COUNT(*) AS EXPECT_1000 FROM t8; + +--connection node_1 +DROP TABLE t1,t2,t3,t4,t5,t6,t7,t8; +# +# View +# +CREATE TABLE t1(pk int not null primary key) engine=innodb; +INSERT INTO t1 values (1),(2),(3),(4); +CREATE VIEW view_t1 AS SELECT * FROM t1; +INSERT INTO view_t1 VALUES (5); +SELECT * FROM t1; +DROP TABLE t1; +DROP VIEW view_t1; +CREATE TABLE t1(pk int not null primary key) engine=myisam; +INSERT INTO t1 values (1),(2),(3),(4); +CREATE VIEW view_t1 AS SELECT * FROM t1; +INSERT INTO view_t1 VALUES (5); +SELECT * FROM t1; +DROP TABLE t1; +DROP VIEW view_t1; +CREATE TABLE t1(pk int not null primary key) engine=aria; +INSERT INTO t1 values (1),(2),(3),(4); +CREATE VIEW view_t1 AS SELECT * FROM t1; +INSERT INTO view_t1 VALUES (5); +SELECT * FROM t1; +DROP TABLE t1; +DROP VIEW view_t1; +SET GLOBAL wsrep_mode=DEFAULT; diff --git a/mysql-test/suite/galera/t/mdev-31285.test b/mysql-test/suite/galera/t/mdev-31285.test index d2749165ef7..5abef37cccd 100644 --- a/mysql-test/suite/galera/t/mdev-31285.test +++ b/mysql-test/suite/galera/t/mdev-31285.test @@ -1,34 +1,15 @@ --source include/galera_cluster.inc ---let $node_1 = node_1 ---let $node_2 = node_2 ---source include/auto_increment_offset_save.inc - --connection node_1 +# +# Below should not cause nodes to be inconsistent (they could if we +# allow TOI as some error are ignored on applier +# +--error ER_NOT_SUPPORTED_YET CREATE TABLE t ENGINE=InnoDB WITH SYSTEM VERSIONING AS SELECT 1 AS i; + +--connection node_2 +--error ER_NO_SUCH_TABLE SHOW CREATE TABLE t; -SELECT * from t; -DROP TABLE IF EXISTS t; -COMMIT; -# -# Restart node_2, force SST because database is inconsistent compared to node_1 -# ---connection node_2 -SET SESSION wsrep_sync_wait=0; ---source include/kill_galera.inc ---remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat ---echo Starting server ... -let $restart_noprint=2; ---source include/start_mysqld.inc ---let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; ---source include/wait_condition.inc ---let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; ---source include/wait_condition.inc - ---connection node_2 -call mtr.add_suppression("WSREP: Event .*Write_rows_v1 apply failed:.*"); -call mtr.add_suppression("SREP: Failed to apply write set: gtid:.*"); - ---source include/auto_increment_offset_restore.inc diff --git a/mysql-test/suite/galera/t/rpl_galera_to_mariadb_clone_slave_using_mariadb-backup.cnf b/mysql-test/suite/galera/t/rpl_galera_to_mariadb_clone_slave_using_mariadb-backup.cnf new file mode 100644 index 00000000000..52fd3093931 --- /dev/null +++ b/mysql-test/suite/galera/t/rpl_galera_to_mariadb_clone_slave_using_mariadb-backup.cnf @@ -0,0 +1 @@ +!include ../galera_2nodes_as_master.cnf diff --git a/mysql-test/suite/galera/t/rpl_galera_to_mariadb_clone_slave_using_mariadb-backup.test b/mysql-test/suite/galera/t/rpl_galera_to_mariadb_clone_slave_using_mariadb-backup.test new file mode 100644 index 00000000000..29590e327fd --- /dev/null +++ b/mysql-test/suite/galera/t/rpl_galera_to_mariadb_clone_slave_using_mariadb-backup.test @@ -0,0 +1,9 @@ +--source include/have_innodb.inc +--source include/galera_cluster.inc + +--echo # +--echo # MDEV-33355 Add a Galera-2-node-to-MariaDB replication MTR test cloning the slave with mariadb-backup +--echo # + +--let cnf=galera2_to_mariadb +--source include/rpl_clone_slave_using_mariadb-backup.inc diff --git a/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result b/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result index 9f1d3fec16e..a69cef11358 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result +++ b/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result @@ -9,6 +9,7 @@ INSERT INTO t1 VALUES (01), (02), (03), (04), (05); connection node_2; Unloading wsrep provider ... SET GLOBAL wsrep_cluster_address = ''; +connection node_1; connection node_3; Unloading wsrep provider ... SET GLOBAL wsrep_cluster_address = ''; @@ -33,14 +34,16 @@ SET GLOBAL wsrep_provider_options = 'dbug='; SET GLOBAL wsrep_provider_options = 'signal=ist_sender_send_after_get_buffers'; INSERT INTO t1 VALUES (51), (52), (53), (54), (55); connection node_2; +connection node_1; connection node_3; +connection node_1; connection node_2; -SELECT COUNT(*) = 30 FROM t1; -COUNT(*) = 30 -1 -SELECT COUNT(*) = 3 FROM t2; -COUNT(*) = 3 -1 +SELECT COUNT(*) AS EXPECT_30 FROM t1; +EXPECT_30 +30 +SELECT COUNT(*) AS EXPECT_3 FROM t2; +EXPECT_3 +3 SELECT LENGTH(f1) = 512 * 1024 FROM t2; LENGTH(f1) = 512 * 1024 1 @@ -48,12 +51,12 @@ LENGTH(f1) = 512 * 1024 1 CALL mtr.add_suppression("WSREP: Unsupported protocol downgrade: incremental data collection disabled"); connection node_3; -SELECT COUNT(*) = 30 FROM t1; -COUNT(*) = 30 -1 -SELECT COUNT(*) = 3 FROM t2; -COUNT(*) = 3 -1 +SELECT COUNT(*) AS EXPECT_30 FROM t1; +EXPECT_30 +30 +SELECT COUNT(*) AS EXPECT_3 FROM t2; +EXPECT_3 +3 SELECT LENGTH(f1) = 512 * 1024 FROM t2; LENGTH(f1) = 512 * 1024 1 diff --git a/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_B.result b/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_B.result index 732385a3966..a88909f4bfb 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_B.result +++ b/mysql-test/suite/galera_3nodes/r/galera_join_with_cc_B.result @@ -92,3 +92,7 @@ connection node_2; call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); connection node_3; call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); +disconnect node_1a; +disconnect node_3; +disconnect node_2; +disconnect node_1; diff --git a/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.cnf b/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.cnf index 303087dffbb..29563657262 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.cnf +++ b/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.cnf @@ -2,10 +2,22 @@ [mysqld.1] wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;pc.ignore_sb=true;gcache.size=1M' +auto_increment_increment=1 +auto_increment_offset=1 +# this will force server restarts before this test +loose-galera-ist-gcache-rollover=1 +wsrep-debug=1 [mysqld.2] wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;pc.ignore_sb=true;gcache.size=1M' +auto_increment_increment=2 +auto_increment_offset=2 +loose-galera-ist-gcache-rollover=2 +wsrep-debug=1 [mysqld.3] wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.3.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;pc.ignore_sb=true;gcache.size=1M' - +auto_increment_increment=3 +auto_increment_offset=3 +loose-galera-ist-gcache-rollover=3 +wsrep-debug=1 diff --git a/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test b/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test index 210a4c2331e..16b9bdb2d02 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test +++ b/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test @@ -12,6 +12,7 @@ --source include/have_innodb.inc --source include/have_debug_sync.inc --source include/galera_have_debug_sync.inc +--source include/force_restart.inc --let $galera_connection_name = node_3 --let $galera_server_number = 3 @@ -24,6 +25,9 @@ --source ../galera/include/auto_increment_offset_save.inc --connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--let $wait_condition_on_error_output = SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE 'wsrep%'; show processlist +--source include/wait_condition_with_debug.inc CREATE TABLE t1 (f1 INTEGER PRIMARY KEY); INSERT INTO t1 VALUES (01), (02), (03), (04), (05); @@ -32,12 +36,15 @@ INSERT INTO t1 VALUES (01), (02), (03), (04), (05); --let $wsrep_cluster_address_orig2 = `select @@wsrep_cluster_address` --source suite/galera/include/galera_stop_replication.inc +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + --connection node_3 --let $wsrep_cluster_address_orig3 = `select @@wsrep_cluster_address` --source suite/galera/include/galera_stop_replication.inc --connection node_1 ---source include/wait_until_connected_again.inc INSERT INTO t1 VALUES (11), (12), (13), (14), (15); # Wait until nodes #2 and #3 have left @@ -88,29 +95,39 @@ INSERT INTO t1 VALUES (51), (52), (53), (54), (55); --connection node_2 --source include/wait_until_connected_again.inc +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 OR VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + --connection node_3 --source include/wait_until_connected_again.inc -sleep 5; +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc # Final checks --connection node_2 -SELECT COUNT(*) = 30 FROM t1; -SELECT COUNT(*) = 3 FROM t2; +--let $wait_condition = SELECT COUNT(*) = 30 FROM t1 +--source include/wait_condition.inc + +SELECT COUNT(*) AS EXPECT_30 FROM t1; +SELECT COUNT(*) AS EXPECT_3 FROM t2; SELECT LENGTH(f1) = 512 * 1024 FROM t2; CALL mtr.add_suppression("WSREP: Unsupported protocol downgrade: incremental data collection disabled"); # Final checks --connection node_3 -SELECT COUNT(*) = 30 FROM t1; -SELECT COUNT(*) = 3 FROM t2; +--let $wait_condition = SELECT COUNT(*) = 30 FROM t1 +--source include/wait_condition.inc +SELECT COUNT(*) AS EXPECT_30 FROM t1; +SELECT COUNT(*) AS EXPECT_3 FROM t2; SELECT LENGTH(f1) = 512 * 1024 FROM t2; CALL mtr.add_suppression("WSREP: Unsupported protocol downgrade: incremental data collection disabled"); DROP TABLE t1, t2; # Restore original auto_increment_offset values. ---source ../galera/include/auto_increment_offset_restore.inc - --let $galera_cluster_size=3 +--source ../galera/include/auto_increment_offset_restore.inc --source include/galera_end.inc diff --git a/mysql-test/suite/galera_3nodes/t/galera_join_with_cc_B.test b/mysql-test/suite/galera_3nodes/t/galera_join_with_cc_B.test index 55d6b458849..d06cdcc8ae4 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_join_with_cc_B.test +++ b/mysql-test/suite/galera_3nodes/t/galera_join_with_cc_B.test @@ -278,4 +278,9 @@ call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State T --connection node_3 call mtr.add_suppression("WSREP: Rejecting JOIN message from \(.*\): new State Transfer required."); +--disconnect node_1a + +# Restore original auto_increment_offset values. +--let $galera_cluster_size=3 --source ../galera/include/auto_increment_offset_restore.inc +--source include/galera_end.inc diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_before_apply.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_before_apply.result index 933038e00f1..ef2bd7a45e1 100644 --- a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_before_apply.result +++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_before_apply.result @@ -7,11 +7,11 @@ connection node_3; connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; connection node_2; -SELECT COUNT(*) = 0 FROM t1; -COUNT(*) = 0 -1 +SELECT COUNT(*) AS EXPECT_0 FROM t1; +EXPECT_0 +0 connection node_1; -CREATE TABLE t2 (f1 INTEGER); +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; LOCK TABLE t2 WRITE; connection node_1; @@ -37,12 +37,12 @@ count_match count_match 1 connection node_1; -SELECT COUNT(*) FROM mysql.wsrep_streaming_log; -COUNT(*) +SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log; +EXPECT_0 0 connection node_2; -SELECT COUNT(*) FROM mysql.wsrep_streaming_log; -COUNT(*) +SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log; +EXPECT_0 0 connection node_1; DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_before_apply.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_before_apply.test index 08a59296e41..355db2de456 100644 --- a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_before_apply.test +++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_before_apply.test @@ -15,18 +15,23 @@ --source ../galera/include/auto_increment_offset_save.inc --connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; # Block node #2's applier before table t1's inserts have come into play --connection node_2 -SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) AS EXPECT_0 FROM t1; --connection node_1 -CREATE TABLE t2 (f1 INTEGER); +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; --connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2' +--source include/wait_condition.inc LOCK TABLE t2 WRITE; --connection node_1 @@ -77,10 +82,10 @@ if ($mysql_errno == 1213) { --enable_query_log --connection node_1 -SELECT COUNT(*) FROM mysql.wsrep_streaming_log; +SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log; --connection node_2 -SELECT COUNT(*) FROM mysql.wsrep_streaming_log; +SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log; --connection node_1 DROP TABLE t1; 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/alter_kill.result b/mysql-test/suite/innodb/r/alter_kill.result index a0d95154ab9..c4469a8c322 100644 --- a/mysql-test/suite/innodb/r/alter_kill.result +++ b/mysql-test/suite/innodb/r/alter_kill.result @@ -14,9 +14,9 @@ disconnect con1; # and recompute innodb_checksum_algorithm=crc32 # restart SELECT COUNT(*) FROM bug16720368; -ERROR 42S02: Table 'test.bug16720368' doesn't exist in engine +ERROR HY000: Table `test`.`bug16720368` is corrupted. Please drop the table and recreate. INSERT INTO bug16720368 VALUES(1); -ERROR HY000: Table test/bug16720368 is corrupted. Please drop the table and recreate. +ERROR HY000: Table `test`.`bug16720368` is corrupted. Please drop the table and recreate. INSERT INTO bug16720368_1 VALUES(1); # Shut down the server to uncorrupt the data. # restart 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/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result index 808e2270e27..80a0afb8d06 100644 --- a/mysql-test/suite/innodb/r/foreign_key.result +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -1035,9 +1035,22 @@ BEGIN; INSERT INTO child SET a=1; ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`a`) REFERENCES `parent` (`a`)) connection default; +TRUNCATE TABLE parent; +ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`a`) REFERENCES `test`.`parent` (`a`)) +DROP TABLE parent; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +SET innodb_lock_wait_timeout=0; +RENAME TABLE parent TO transparent; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +ALTER TABLE parent FORCE, ALGORITHM=COPY; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +ALTER TABLE parent FORCE, ALGORITHM=INPLACE; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET innodb_lock_wait_timeout=0, foreign_key_checks=0; TRUNCATE TABLE parent; ERROR HY000: Lock wait timeout exceeded; try restarting transaction +DROP TABLE parent; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction ALTER TABLE parent FORCE, ALGORITHM=COPY; ERROR HY000: Lock wait timeout exceeded; try restarting transaction ALTER TABLE parent FORCE, ALGORITHM=INPLACE; @@ -1052,7 +1065,13 @@ TRUNCATE TABLE parent; ALTER TABLE parent FORCE, ALGORITHM=COPY; ALTER TABLE parent FORCE, ALGORITHM=INPLACE; ALTER TABLE parent ADD COLUMN b INT, ALGORITHM=INSTANT; -DROP TABLE child, parent; +SET foreign_key_checks=ON; +TRUNCATE TABLE parent; +ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`a`) REFERENCES `test`.`parent` (`a`)) +ALTER TABLE parent FORCE, ALGORITHM=COPY; +ALTER TABLE parent FORCE, ALGORITHM=INPLACE; +RENAME TABLE parent TO transparent; +DROP TABLE child, transparent; # # MDEV-26217 Failing assertion: list.count > 0 in ut_list_remove # or Assertion `lock->trx == this' failed in dberr_t trx_t::drop_table diff --git a/mysql-test/suite/innodb/r/full_crc32_import.result b/mysql-test/suite/innodb/r/full_crc32_import.result index 548e69c1c52..416f607cc33 100644 --- a/mysql-test/suite/innodb/r/full_crc32_import.result +++ b/mysql-test/suite/innodb/r/full_crc32_import.result @@ -50,7 +50,15 @@ t1 CREATE TABLE `t1` ( `b` blob DEFAULT NULL, `c` blob DEFAULT NULL, PRIMARY KEY (`a`) -) ENGINE=InnoDB AUTO_INCREMENT=57 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=DYNAMIC +) ENGINE=InnoDB AUTO_INCREMENT=46 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=DYNAMIC +# Auto increment value must be more than maximum column value +SELECT MAX(a) FROM t1; +MAX(a) +45 +SELECT auto_increment FROM information_schema.tables +WHERE table_name like 't1'; +auto_increment +46 UPDATE t1 set b = repeat("de", 100) where b = repeat("cd", 200); explain SELECT a FROM t1 where b = repeat("de", 100); id select_type table type possible_keys key key_len ref rows Extra @@ -132,7 +140,15 @@ t1 CREATE TABLE `t1` ( `c2` point NOT NULL, `c3` linestring NOT NULL, PRIMARY KEY (`c1`) -) ENGINE=InnoDB AUTO_INCREMENT=16372 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=DYNAMIC +) ENGINE=InnoDB AUTO_INCREMENT=14325 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=DYNAMIC +# Auto increment value must be more than maximum column value +SELECT MAX(c1) FROM t1; +MAX(c1) +14324 +SELECT auto_increment FROM information_schema.tables +WHERE table_name like 't1'; +auto_increment +14325 UPDATE t1 SET C2 = ST_GeomFromText('POINT(0 0)'); SELECT COUNT(*) FROM t1; COUNT(*) diff --git a/mysql-test/suite/innodb/r/import_bugs.result b/mysql-test/suite/innodb/r/import_bugs.result index 98f3e76763b..26845e55567 100644 --- a/mysql-test/suite/innodb/r/import_bugs.result +++ b/mysql-test/suite/innodb/r/import_bugs.result @@ -15,6 +15,58 @@ CREATE TABLE imp_t1 (a INT PRIMARY KEY) ENGINE=InnoDB; DROP TABLE imp_t1, t1; SET GLOBAL innodb_checksum_algorithm=@save_innodb_checksum_algorithm; # +# MDEV-33400 Adaptive hash index corruption after DISCARD TABLESPACE +# +SET @save_adaptive=@@GLOBAL.innodb_adaptive_hash_index; +SET GLOBAL innodb_adaptive_hash_index=ON; +CREATE TABLE t (a INT PRIMARY KEY) ENGINE=INNODB; +INSERT INTO t SELECT * FROM seq_1_to_131; +ALTER TABLE t ADD hid INT DEFAULT 2; +INSERT INTO t VALUES (251,1); +ALTER TABLE t DISCARD TABLESPACE; +CHECK TABLE mysql.innodb_table_stats; +Table Op Msg_type Msg_text +mysql.innodb_table_stats check status OK +DROP TABLE t; +SET GLOBAL innodb_adaptive_hash_index=@save_adaptive; +# End of 10.4 tests +# +# MDEV-18288: Transportable Tablespaces leave AUTO_INCREMENT in mismatched +# state, causing INSERT errors in newly imported tables when .cfg is not used. +# +CREATE TABLE t1( +id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, +PRIMARY KEY (id) +) ENGINE=INNODB; +CREATE TABLE t2 LIKE t1; +ALTER TABLE t2 DISCARD TABLESPACE; +INSERT INTO t1() VALUES(); +INSERT INTO t1() VALUES(); +FLUSH TABLES test.t1 FOR EXPORT; +# Copy data file +# Skip CFG file copy +UNLOCK TABLES; +DROP TABLE t1; +ALTER TABLE t2 IMPORT TABLESPACE; +Warnings: +Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t2.cfg', will attempt to import without schema verification +SELECT * FROM t2 ORDER BY id; +id +1 +2 +INSERT INTO t2() VALUES(); +INSERT INTO t2() VALUES(); +INSERT INTO t2() VALUES(); +SELECT * FROM t2 ORDER BY id; +id +1 +2 +3 +4 +5 +DROP TABLE t2; +# End of 10.5 tests +# # MDEV-27006 Assertion `!lock_trx_has_sys_table_locks(trx)' # failed in dberr_t row_discard_tablespace_for_mysql # (dict_table_t*, trx_t*) diff --git a/mysql-test/suite/innodb/r/innodb_ut_format_name.result b/mysql-test/suite/innodb/r/innodb_ut_format_name.result deleted file mode 100644 index 41a5b0f7149..00000000000 --- a/mysql-test/suite/innodb/r/innodb_ut_format_name.result +++ /dev/null @@ -1,5 +0,0 @@ -CREATE TABLE t (c INT) ENGINE=INNODB; -SET @save_dbug = @@debug_dbug; -SET debug_dbug = '+d,test_ut_format_name'; -DROP TABLE t; -SET debug_dbug = @save_dbug; diff --git a/mysql-test/suite/innodb/r/undo_space_dblwr.result b/mysql-test/suite/innodb/r/undo_space_dblwr.result index d6822b20eb7..4466df9857b 100644 --- a/mysql-test/suite/innodb/r/undo_space_dblwr.result +++ b/mysql-test/suite/innodb/r/undo_space_dblwr.result @@ -4,15 +4,14 @@ Variable_name Value innodb_doublewrite ON create table t1(f1 int not null, f2 int not null)engine=innodb; insert into t1 values (1, 1); -InnoDB 0 transactions not purged -set GLOBAL innodb_log_checkpoint_now=1; +SET GLOBAL innodb_fast_shutdown = 0; +# restart: --debug_dbug=+d,ib_log_checkpoint_avoid_hard --innodb_flush_sync=0 # Make the first page dirty for undo tablespace set global innodb_saved_page_number_debug = 0; set global innodb_fil_make_page_dirty_debug = 1; -SET GLOBAL innodb_max_dirty_pages_pct_lwm=0.0; -SET GLOBAL innodb_max_dirty_pages_pct=0.0; +SET GLOBAL innodb_buf_flush_list_now = 1; # Kill the server -# restart +# restart: --debug_dbug=+d,ib_log_checkpoint_avoid_hard --innodb_flush_sync=0 FOUND 1 /Checksum mismatch in the first page of file/ in mysqld.1.err check table t1; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/innodb/t/alter_kill.test b/mysql-test/suite/innodb/t/alter_kill.test index 57ca97f003d..798f9af00db 100644 --- a/mysql-test/suite/innodb/t/alter_kill.test +++ b/mysql-test/suite/innodb/t/alter_kill.test @@ -75,7 +75,7 @@ EOF -- source include/start_mysqld.inc ---error ER_NO_SUCH_TABLE_IN_ENGINE +--error ER_TABLE_CORRUPT SELECT COUNT(*) FROM bug16720368; --error ER_TABLE_CORRUPT INSERT INTO bug16720368 VALUES(1); 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/innodb/t/corrupted_during_recovery.test b/mysql-test/suite/innodb/t/corrupted_during_recovery.test index 1f410246840..8324054992c 100644 --- a/mysql-test/suite/innodb/t/corrupted_during_recovery.test +++ b/mysql-test/suite/innodb/t/corrupted_during_recovery.test @@ -7,7 +7,7 @@ call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE faile call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed read of file '.*test.t1\\.ibd' page"); call mtr.add_suppression("InnoDB: Failed to read page 3 from file '.*test.t1\\.ibd': Page read from tablespace is corrupted."); call mtr.add_suppression("InnoDB: (Unable to apply log to|Discarding log for) corrupted page .*, page number=3\\]"); -call mtr.add_suppression("Table test/t1 is corrupted. Please drop the table and recreate\\."); +call mtr.add_suppression("Table `test`.`t1` is corrupted. Please drop the table and recreate."); call mtr.add_suppression("InnoDB: File '.*test/t1\\.ibd' is corrupted"); call mtr.add_suppression("InnoDB: A long wait .* was observed for dict_sys"); --enable_query_log diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test index 0db3a7ca377..e793e261abd 100644 --- a/mysql-test/suite/innodb/t/foreign_key.test +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -1077,10 +1077,23 @@ BEGIN; --error ER_NO_REFERENCED_ROW_2 INSERT INTO child SET a=1; connection default; +--error ER_TRUNCATE_ILLEGAL_FK +TRUNCATE TABLE parent; +--error ER_ROW_IS_REFERENCED_2 +DROP TABLE parent; +SET innodb_lock_wait_timeout=0; +--error ER_LOCK_WAIT_TIMEOUT +RENAME TABLE parent TO transparent; +--error ER_LOCK_WAIT_TIMEOUT +ALTER TABLE parent FORCE, ALGORITHM=COPY; +--error ER_LOCK_WAIT_TIMEOUT +ALTER TABLE parent FORCE, ALGORITHM=INPLACE; SET innodb_lock_wait_timeout=0, foreign_key_checks=0; --error ER_LOCK_WAIT_TIMEOUT TRUNCATE TABLE parent; --error ER_LOCK_WAIT_TIMEOUT +DROP TABLE parent; +--error ER_LOCK_WAIT_TIMEOUT ALTER TABLE parent FORCE, ALGORITHM=COPY; --error ER_LOCK_WAIT_TIMEOUT ALTER TABLE parent FORCE, ALGORITHM=INPLACE; @@ -1095,7 +1108,13 @@ TRUNCATE TABLE parent; ALTER TABLE parent FORCE, ALGORITHM=COPY; ALTER TABLE parent FORCE, ALGORITHM=INPLACE; ALTER TABLE parent ADD COLUMN b INT, ALGORITHM=INSTANT; -DROP TABLE child, parent; +SET foreign_key_checks=ON; +--error ER_TRUNCATE_ILLEGAL_FK +TRUNCATE TABLE parent; +ALTER TABLE parent FORCE, ALGORITHM=COPY; +ALTER TABLE parent FORCE, ALGORITHM=INPLACE; +RENAME TABLE parent TO transparent; +DROP TABLE child, transparent; --echo # --echo # MDEV-26217 Failing assertion: list.count > 0 in ut_list_remove diff --git a/mysql-test/suite/innodb/t/full_crc32_import.test b/mysql-test/suite/innodb/t/full_crc32_import.test index 0eb31f8d63f..6f02b2ab7e8 100644 --- a/mysql-test/suite/innodb/t/full_crc32_import.test +++ b/mysql-test/suite/innodb/t/full_crc32_import.test @@ -63,6 +63,12 @@ ALTER TABLE t1 DROP INDEX b; ALTER TABLE t1 IMPORT TABLESPACE; --enable_warnings SHOW CREATE TABLE t1; + +--echo # Auto increment value must be more than maximum column value +SELECT MAX(a) FROM t1; +SELECT auto_increment FROM information_schema.tables +WHERE table_name like 't1'; + UPDATE t1 set b = repeat("de", 100) where b = repeat("cd", 200); --replace_column 9 # explain SELECT a FROM t1 where b = repeat("de", 100); @@ -145,6 +151,12 @@ ALTER TABLE t1 DROP INDEX idx1; ALTER TABLE t1 IMPORT TABLESPACE; --disable_warnings SHOW CREATE TABLE t1; + +--echo # Auto increment value must be more than maximum column value +SELECT MAX(c1) FROM t1; +SELECT auto_increment FROM information_schema.tables +WHERE table_name like 't1'; + UPDATE t1 SET C2 = ST_GeomFromText('POINT(0 0)'); SELECT COUNT(*) FROM t1; DELETE FROM t1; diff --git a/mysql-test/suite/innodb/t/import_bugs.test b/mysql-test/suite/innodb/t/import_bugs.test index 7fcab9f9abc..d22b4b67272 100644 --- a/mysql-test/suite/innodb/t/import_bugs.test +++ b/mysql-test/suite/innodb/t/import_bugs.test @@ -1,4 +1,5 @@ --source include/have_innodb.inc +--source include/have_sequence.inc call mtr.add_suppression("Index for table 'imp_t1' is corrupt; try to repair it"); @@ -22,6 +23,67 @@ DROP TABLE imp_t1, t1; SET GLOBAL innodb_checksum_algorithm=@save_innodb_checksum_algorithm; +--echo # +--echo # MDEV-33400 Adaptive hash index corruption after DISCARD TABLESPACE +--echo # + +SET @save_adaptive=@@GLOBAL.innodb_adaptive_hash_index; +SET GLOBAL innodb_adaptive_hash_index=ON; + +CREATE TABLE t (a INT PRIMARY KEY) ENGINE=INNODB; +INSERT INTO t SELECT * FROM seq_1_to_131; +ALTER TABLE t ADD hid INT DEFAULT 2; +INSERT INTO t VALUES (251,1); +ALTER TABLE t DISCARD TABLESPACE; +CHECK TABLE mysql.innodb_table_stats; +DROP TABLE t; +SET GLOBAL innodb_adaptive_hash_index=@save_adaptive; + +--echo # End of 10.4 tests + +--echo # +--echo # MDEV-18288: Transportable Tablespaces leave AUTO_INCREMENT in mismatched +--echo # state, causing INSERT errors in newly imported tables when .cfg is not used. +--echo # + +CREATE TABLE t1( + id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + PRIMARY KEY (id) +) ENGINE=INNODB; + +CREATE TABLE t2 LIKE t1; + +ALTER TABLE t2 DISCARD TABLESPACE; + +INSERT INTO t1() VALUES(); +INSERT INTO t1() VALUES(); + +FLUSH TABLES test.t1 FOR EXPORT; + +--echo # Copy data file +--copy_file $datadir/test/t1.ibd $datadir/test/t2.ibd + +--echo # Skip CFG file copy +#--copy_file $datadir/test/t1.cfg $datadir/test/t2.cfg +--remove_file $datadir/test/t1.cfg + +UNLOCK TABLES; +DROP TABLE t1; + +--replace_regex /opening '.*\/test\//opening '.\/test\// +ALTER TABLE t2 IMPORT TABLESPACE; + +SELECT * FROM t2 ORDER BY id; + +INSERT INTO t2() VALUES(); +INSERT INTO t2() VALUES(); +INSERT INTO t2() VALUES(); + +SELECT * FROM t2 ORDER BY id; +DROP TABLE t2; + +--echo # End of 10.5 tests + --echo # --echo # MDEV-27006 Assertion `!lock_trx_has_sys_table_locks(trx)' --echo # failed in dberr_t row_discard_tablespace_for_mysql diff --git a/mysql-test/suite/innodb/t/innodb_ut_format_name.test b/mysql-test/suite/innodb/t/innodb_ut_format_name.test deleted file mode 100644 index 6e4023c7088..00000000000 --- a/mysql-test/suite/innodb/t/innodb_ut_format_name.test +++ /dev/null @@ -1,17 +0,0 @@ -# -# Test ut_format_name() -# - --- source include/have_debug.inc --- source include/have_innodb.inc - -CREATE TABLE t (c INT) ENGINE=INNODB; - -# This will invoke test_ut_format_name() in debug builds - -SET @save_dbug = @@debug_dbug; -SET debug_dbug = '+d,test_ut_format_name'; - -DROP TABLE t; - -SET debug_dbug = @save_dbug; diff --git a/mysql-test/suite/innodb/t/undo_space_dblwr.test b/mysql-test/suite/innodb/t/undo_space_dblwr.test index b6fd6738a1c..3f61e91ddf5 100644 --- a/mysql-test/suite/innodb/t/undo_space_dblwr.test +++ b/mysql-test/suite/innodb/t/undo_space_dblwr.test @@ -9,19 +9,19 @@ show variables like 'innodb_doublewrite'; create table t1(f1 int not null, f2 int not null)engine=innodb; insert into t1 values (1, 1); ---source include/wait_all_purged.inc +# Slow shutdown and restart to make sure ibuf merge is finished +SET GLOBAL innodb_fast_shutdown = 0; +let $shutdown_timeout=; +let $restart_parameters="--debug_dbug=+d,ib_log_checkpoint_avoid_hard --innodb_flush_sync=0"; +--source include/restart_mysqld.inc -set GLOBAL innodb_log_checkpoint_now=1; --source ../include/no_checkpoint_start.inc - --echo # Make the first page dirty for undo tablespace set global innodb_saved_page_number_debug = 0; set global innodb_fil_make_page_dirty_debug = 1; -SET GLOBAL innodb_max_dirty_pages_pct_lwm=0.0; -SET GLOBAL innodb_max_dirty_pages_pct=0.0; +SET GLOBAL innodb_buf_flush_list_now = 1; -sleep 1; --let CLEANUP_IF_CHECKPOINT=drop table t1; --source ../include/no_checkpoint_end.inc diff --git a/mysql-test/suite/innodb_fts/r/create,orig.rdiff b/mysql-test/suite/innodb_fts/r/create,orig.rdiff new file mode 100644 index 00000000000..e7191646735 --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/create,orig.rdiff @@ -0,0 +1,11 @@ +--- create.result ++++ create.reject +@@ -207,7 +207,7 @@ + UNIQUE KEY `FTS_DOC_ID_INDEX` (`FTS_DOC_ID` DESC) + ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci + ALTER TABLE t1 ADD FULLTEXT INDEX(b), ALGORITHM=INPLACE; +-ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Not implemented for system-versioned operations. Try ALGORITHM=COPY ++ERROR HY000: Index 'FTS_DOC_ID_INDEX' is of wrong type for an InnoDB FULLTEXT index + ALTER TABLE t1 ADD FULLTEXT INDEX(b), ALGORITHM=COPY; + ERROR HY000: Index 'FTS_DOC_ID_INDEX' is of wrong type for an InnoDB FULLTEXT index + DROP TABLE t1; diff --git a/mysql-test/suite/innodb_fts/r/create.result b/mysql-test/suite/innodb_fts/r/create.result index 4334344a981..04fc20195b6 100644 --- a/mysql-test/suite/innodb_fts/r/create.result +++ b/mysql-test/suite/innodb_fts/r/create.result @@ -207,7 +207,7 @@ t1 CREATE TABLE `t1` ( UNIQUE KEY `FTS_DOC_ID_INDEX` (`FTS_DOC_ID` DESC) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ALTER TABLE t1 ADD FULLTEXT INDEX(b), ALGORITHM=INPLACE; -ERROR HY000: Index 'FTS_DOC_ID_INDEX' is of wrong type for an InnoDB FULLTEXT index +ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Not implemented for system-versioned operations. Try ALGORITHM=COPY ALTER TABLE t1 ADD FULLTEXT INDEX(b), ALGORITHM=COPY; ERROR HY000: Index 'FTS_DOC_ID_INDEX' is of wrong type for an InnoDB FULLTEXT index DROP TABLE t1; diff --git a/mysql-test/suite/innodb_fts/r/innodb-fts-ddl,vers.rdiff b/mysql-test/suite/innodb_fts/r/innodb-fts-ddl,vers.rdiff new file mode 100644 index 00000000000..d46275ff4e4 --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/innodb-fts-ddl,vers.rdiff @@ -0,0 +1,57 @@ +--- innodb-fts-ddl.result ++++ innodb-fts-ddl.reject +@@ -11,8 +11,10 @@ + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=NOCOPY; +-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +-ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=INPLACE; ++ERROR 0A000: ALGORITHM=NOCOPY is not supported. Reason: Not implemented for system-versioned operations. Try ALGORITHM=COPY ++ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body); ++affected rows: 6 ++info: Records: 6 Duplicates: 0 Warnings: 0 + SELECT * FROM fts_test WHERE MATCH (title, body) + AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); + id title body +@@ -26,7 +28,9 @@ + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); +-ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=NOCOPY; ++ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body); ++affected rows: 12 ++info: Records: 12 Duplicates: 0 Warnings: 0 + SELECT * FROM fts_test WHERE MATCH (title, body) + AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); + id title body +@@ -76,8 +80,10 @@ + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + CREATE FULLTEXT INDEX idx on fts_test (title, body) LOCK=NONE; +-ERROR 0A000: LOCK=NONE is not supported. Reason: Fulltext index creation requires a lock. Try LOCK=SHARED +-ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=NOCOPY; ++ERROR 0A000: LOCK=NONE is not supported. Reason: Not implemented for system-versioned operations. Try LOCK=SHARED ++ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body); ++affected rows: 6 ++info: Records: 6 Duplicates: 0 Warnings: 0 + ALTER TABLE fts_test ROW_FORMAT=REDUNDANT, LOCK=NONE; + ERROR 0A000: LOCK=NONE is not supported. Reason: Fulltext index creation requires a lock. Try LOCK=SHARED + ALTER TABLE fts_test ROW_FORMAT=REDUNDANT; +@@ -162,7 +168,7 @@ + (20, 'MySQL Security','When configured properly, MySQL ...'); + ALTER TABLE articles ADD FULLTEXT INDEX idx (title), + ADD FULLTEXT INDEX idx3 (title), ALGORITHM=INPLACE; +-ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: InnoDB presently supports one FULLTEXT index creation at a time. Try ALGORITHM=COPY ++ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Not implemented for system-versioned operations. Try ALGORITHM=COPY + ALTER TABLE articles ADD FULLTEXT INDEX idx (title), + ADD FULLTEXT INDEX idx3 (title); + affected rows: 6 +@@ -274,7 +280,7 @@ + call mtr.add_suppression("InnoDB: Failed to create"); + CREATE TABLE t1(a TEXT, FTS_DOC_ID BIGINT UNSIGNED NOT NULL UNIQUE) ENGINE=InnoDB; + ALTER TABLE t1 ADD FULLTEXT(a), ALGORITHM=INPLACE; +-ERROR HY000: Got error 11 "Resource temporarily unavailable" from storage engine InnoDB ++ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Not implemented for system-versioned operations. Try ALGORITHM=COPY + DROP TABLE t1; + CREATE TABLE t1 (a VARCHAR(3)) ENGINE=InnoDB; + ALTER TABLE t1 ADD FULLTEXT KEY(a), ADD COLUMN b VARCHAR(3), ADD FULLTEXT KEY(b); diff --git a/mysql-test/suite/innodb_fts/r/innodb-fts-ddl,vers_trx.rdiff b/mysql-test/suite/innodb_fts/r/innodb-fts-ddl,vers_trx.rdiff new file mode 100644 index 00000000000..d46275ff4e4 --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/innodb-fts-ddl,vers_trx.rdiff @@ -0,0 +1,57 @@ +--- innodb-fts-ddl.result ++++ innodb-fts-ddl.reject +@@ -11,8 +11,10 @@ + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=NOCOPY; +-ERROR 0A000: ALGORITHM=NOCOPY is not supported for this operation. Try ALGORITHM=INPLACE +-ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=INPLACE; ++ERROR 0A000: ALGORITHM=NOCOPY is not supported. Reason: Not implemented for system-versioned operations. Try ALGORITHM=COPY ++ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body); ++affected rows: 6 ++info: Records: 6 Duplicates: 0 Warnings: 0 + SELECT * FROM fts_test WHERE MATCH (title, body) + AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); + id title body +@@ -26,7 +28,9 @@ + ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); +-ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=NOCOPY; ++ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body); ++affected rows: 12 ++info: Records: 12 Duplicates: 0 Warnings: 0 + SELECT * FROM fts_test WHERE MATCH (title, body) + AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE); + id title body +@@ -76,8 +80,10 @@ + ('MySQL vs. YourSQL','In the following database comparison ...'), + ('MySQL Security','When configured properly, MySQL ...'); + CREATE FULLTEXT INDEX idx on fts_test (title, body) LOCK=NONE; +-ERROR 0A000: LOCK=NONE is not supported. Reason: Fulltext index creation requires a lock. Try LOCK=SHARED +-ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=NOCOPY; ++ERROR 0A000: LOCK=NONE is not supported. Reason: Not implemented for system-versioned operations. Try LOCK=SHARED ++ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body); ++affected rows: 6 ++info: Records: 6 Duplicates: 0 Warnings: 0 + ALTER TABLE fts_test ROW_FORMAT=REDUNDANT, LOCK=NONE; + ERROR 0A000: LOCK=NONE is not supported. Reason: Fulltext index creation requires a lock. Try LOCK=SHARED + ALTER TABLE fts_test ROW_FORMAT=REDUNDANT; +@@ -162,7 +168,7 @@ + (20, 'MySQL Security','When configured properly, MySQL ...'); + ALTER TABLE articles ADD FULLTEXT INDEX idx (title), + ADD FULLTEXT INDEX idx3 (title), ALGORITHM=INPLACE; +-ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: InnoDB presently supports one FULLTEXT index creation at a time. Try ALGORITHM=COPY ++ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Not implemented for system-versioned operations. Try ALGORITHM=COPY + ALTER TABLE articles ADD FULLTEXT INDEX idx (title), + ADD FULLTEXT INDEX idx3 (title); + affected rows: 6 +@@ -274,7 +280,7 @@ + call mtr.add_suppression("InnoDB: Failed to create"); + CREATE TABLE t1(a TEXT, FTS_DOC_ID BIGINT UNSIGNED NOT NULL UNIQUE) ENGINE=InnoDB; + ALTER TABLE t1 ADD FULLTEXT(a), ALGORITHM=INPLACE; +-ERROR HY000: Got error 11 "Resource temporarily unavailable" from storage engine InnoDB ++ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Not implemented for system-versioned operations. Try ALGORITHM=COPY + DROP TABLE t1; + CREATE TABLE t1 (a VARCHAR(3)) ENGINE=InnoDB; + ALTER TABLE t1 ADD FULLTEXT KEY(a), ADD COLUMN b VARCHAR(3), ADD FULLTEXT KEY(b); diff --git a/mysql-test/suite/innodb_fts/r/innodb-fts-fic,vers.rdiff b/mysql-test/suite/innodb_fts/r/innodb-fts-fic,vers.rdiff new file mode 100644 index 00000000000..f9ba217769f --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/innodb-fts-fic,vers.rdiff @@ -0,0 +1,10 @@ +--- innodb-fts-fic.result ++++ innodb-fts-fic.reject +@@ -172,7 +172,6 @@ + (1, 'MySQL Tutorial','DBMS stands for DataBase ...'), + (2, 'How To Use MySQL Well','After you went through a ...'); + CREATE FULLTEXT INDEX idx ON wp(title, text); +-ERROR HY000: Column 'FTS_DOC_ID' is of wrong type for an InnoDB FULLTEXT index + DROP TABLE wp; + CREATE TABLE wp( + FTS_DOC_ID bigint unsigned PRIMARY KEY, diff --git a/mysql-test/suite/innodb_fts/r/innodb-fts-fic,vers_trx.rdiff b/mysql-test/suite/innodb_fts/r/innodb-fts-fic,vers_trx.rdiff new file mode 100644 index 00000000000..f9ba217769f --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/innodb-fts-fic,vers_trx.rdiff @@ -0,0 +1,10 @@ +--- innodb-fts-fic.result ++++ innodb-fts-fic.reject +@@ -172,7 +172,6 @@ + (1, 'MySQL Tutorial','DBMS stands for DataBase ...'), + (2, 'How To Use MySQL Well','After you went through a ...'); + CREATE FULLTEXT INDEX idx ON wp(title, text); +-ERROR HY000: Column 'FTS_DOC_ID' is of wrong type for an InnoDB FULLTEXT index + DROP TABLE wp; + CREATE TABLE wp( + FTS_DOC_ID bigint unsigned PRIMARY KEY, diff --git a/mysql-test/suite/innodb_fts/r/misc_debug,vers.rdiff b/mysql-test/suite/innodb_fts/r/misc_debug,vers.rdiff new file mode 100644 index 00000000000..69294a5a84c --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/misc_debug,vers.rdiff @@ -0,0 +1,66 @@ +--- misc_debug.result ++++ misc_debug.reject +@@ -7,14 +7,14 @@ + SET @saved_debug_dbug = @@SESSION.debug_dbug; + SET SESSION debug_dbug="+d,ib_dict_create_index_tree_fail"; + CREATE FULLTEXT INDEX idx ON articles(body); +-ERROR HY000: Out of memory. ++ERROR HY000: Can't create table `test`.`articles` (errno: 128 "Out of memory in engine") + SET SESSION debug_dbug=@saved_debug_dbug; + ALTER TABLE articles STATS_PERSISTENT=DEFAULT; + DROP TABLE articles; + CREATE TABLE t (a INT, b TEXT) engine=innodb; + SET debug_dbug='+d,alter_table_rollback_new_index'; +-ALTER TABLE t ADD FULLTEXT INDEX (b(64)); +-ERROR HY000: Unknown error ++ALTER TABLE t ADD FULLTEXT INDEX (b(64)), ALGORITHM=INPLACE; ++ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Not implemented for system-versioned operations. Try ALGORITHM=COPY + SET SESSION debug_dbug=@saved_debug_dbug; + DROP TABLE t; + CREATE TABLE t1 (pk INT, a VARCHAR(8), PRIMARY KEY(pk), +@@ -28,32 +28,6 @@ + DROP TABLE t2, t1; + SET SESSION debug_dbug=@saved_debug_dbug; + # +-# MDEV-25200 Index count mismatch due to aborted FULLTEXT INDEX +-# +-CREATE TABLE t1(a INT, b TEXT, c TEXT, FULLTEXT INDEX(b)) ENGINE=InnoDB; +-INSERT INTO t1 VALUES(1, "test", "test_1"); +-connect con1,localhost,root,,test; +-SET DEBUG_DBUG="+d,innodb_OOM_inplace_alter"; +-SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL s2 WAIT_FOR g2'; +-ALTER TABLE t1 ADD FULLTEXT(c); +-connection default; +-SET DEBUG_SYNC='now WAIT_FOR s2'; +-START TRANSACTION; +-SELECT * FROM t1; +-a b c +-1 test test_1 +-SET DEBUG_SYNC='now SIGNAL g2'; +-connection con1; +-ERROR HY000: Out of memory. +-disconnect con1; +-connection default; +-SET DEBUG_SYNC=RESET; +-ALTER TABLE t1 ADD bl INT AS (LENGTH(b)) VIRTUAL; +-CHECK TABLE t1; +-Table Op Msg_type Msg_text +-test.t1 check status OK +-DROP TABLE t1; +-# + # MDEV-25663 Double free of transaction during TRUNCATE + # + call mtr.add_suppression("InnoDB: \\(Too many concurrent transactions\\)"); +@@ -65,12 +39,3 @@ + SET debug_dbug=@saved_debug_dbug; + DROP TABLE t1; + # End of 10.3 tests +-CREATE TABLE t1(f1 INT NOT NULL, f2 CHAR(100))ENGINE=InnoDB; +-SET DEBUG_DBUG="+d,stats_lock_fail"; +-ALTER TABLE t1 ADD FULLTEXT(f2); +-ERROR HY000: Lock wait timeout exceeded; try restarting transaction +-SET debug_dbug=@saved_debug_dbug; +-ALTER TABLE t1 DISCARD TABLESPACE; +-ALTER TABLE t1 ADD FULLTEXT(f2); +-ERROR HY000: Tablespace has been discarded for table `t1` +-DROP TABLE t1; diff --git a/mysql-test/suite/innodb_fts/r/misc_debug,vers_trx.rdiff b/mysql-test/suite/innodb_fts/r/misc_debug,vers_trx.rdiff new file mode 100644 index 00000000000..69294a5a84c --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/misc_debug,vers_trx.rdiff @@ -0,0 +1,66 @@ +--- misc_debug.result ++++ misc_debug.reject +@@ -7,14 +7,14 @@ + SET @saved_debug_dbug = @@SESSION.debug_dbug; + SET SESSION debug_dbug="+d,ib_dict_create_index_tree_fail"; + CREATE FULLTEXT INDEX idx ON articles(body); +-ERROR HY000: Out of memory. ++ERROR HY000: Can't create table `test`.`articles` (errno: 128 "Out of memory in engine") + SET SESSION debug_dbug=@saved_debug_dbug; + ALTER TABLE articles STATS_PERSISTENT=DEFAULT; + DROP TABLE articles; + CREATE TABLE t (a INT, b TEXT) engine=innodb; + SET debug_dbug='+d,alter_table_rollback_new_index'; +-ALTER TABLE t ADD FULLTEXT INDEX (b(64)); +-ERROR HY000: Unknown error ++ALTER TABLE t ADD FULLTEXT INDEX (b(64)), ALGORITHM=INPLACE; ++ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Not implemented for system-versioned operations. Try ALGORITHM=COPY + SET SESSION debug_dbug=@saved_debug_dbug; + DROP TABLE t; + CREATE TABLE t1 (pk INT, a VARCHAR(8), PRIMARY KEY(pk), +@@ -28,32 +28,6 @@ + DROP TABLE t2, t1; + SET SESSION debug_dbug=@saved_debug_dbug; + # +-# MDEV-25200 Index count mismatch due to aborted FULLTEXT INDEX +-# +-CREATE TABLE t1(a INT, b TEXT, c TEXT, FULLTEXT INDEX(b)) ENGINE=InnoDB; +-INSERT INTO t1 VALUES(1, "test", "test_1"); +-connect con1,localhost,root,,test; +-SET DEBUG_DBUG="+d,innodb_OOM_inplace_alter"; +-SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL s2 WAIT_FOR g2'; +-ALTER TABLE t1 ADD FULLTEXT(c); +-connection default; +-SET DEBUG_SYNC='now WAIT_FOR s2'; +-START TRANSACTION; +-SELECT * FROM t1; +-a b c +-1 test test_1 +-SET DEBUG_SYNC='now SIGNAL g2'; +-connection con1; +-ERROR HY000: Out of memory. +-disconnect con1; +-connection default; +-SET DEBUG_SYNC=RESET; +-ALTER TABLE t1 ADD bl INT AS (LENGTH(b)) VIRTUAL; +-CHECK TABLE t1; +-Table Op Msg_type Msg_text +-test.t1 check status OK +-DROP TABLE t1; +-# + # MDEV-25663 Double free of transaction during TRUNCATE + # + call mtr.add_suppression("InnoDB: \\(Too many concurrent transactions\\)"); +@@ -65,12 +39,3 @@ + SET debug_dbug=@saved_debug_dbug; + DROP TABLE t1; + # End of 10.3 tests +-CREATE TABLE t1(f1 INT NOT NULL, f2 CHAR(100))ENGINE=InnoDB; +-SET DEBUG_DBUG="+d,stats_lock_fail"; +-ALTER TABLE t1 ADD FULLTEXT(f2); +-ERROR HY000: Lock wait timeout exceeded; try restarting transaction +-SET debug_dbug=@saved_debug_dbug; +-ALTER TABLE t1 DISCARD TABLESPACE; +-ALTER TABLE t1 ADD FULLTEXT(f2); +-ERROR HY000: Tablespace has been discarded for table `t1` +-DROP TABLE t1; diff --git a/mysql-test/suite/innodb_fts/r/sync_ddl,vers.rdiff b/mysql-test/suite/innodb_fts/r/sync_ddl,vers.rdiff new file mode 100644 index 00000000000..7834e04c9f3 --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/sync_ddl,vers.rdiff @@ -0,0 +1,12 @@ +--- sync_ddl.result ++++ sync_ddl.reject +@@ -100,7 +100,7 @@ + ADD COLUMN id2 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + DROP INDEX idx1, + ADD FULLTEXT INDEX idx2(value); +-affected rows: 0 +-info: Records: 0 Duplicates: 0 Warnings: 0 ++affected rows: 2 ++info: Records: 2 Duplicates: 0 Warnings: 0 + DROP TABLE t1; + SET GLOBAL debug_dbug = @save_debug; diff --git a/mysql-test/suite/innodb_fts/r/sync_ddl,vers_trx.rdiff b/mysql-test/suite/innodb_fts/r/sync_ddl,vers_trx.rdiff new file mode 100644 index 00000000000..7834e04c9f3 --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/sync_ddl,vers_trx.rdiff @@ -0,0 +1,12 @@ +--- sync_ddl.result ++++ sync_ddl.reject +@@ -100,7 +100,7 @@ + ADD COLUMN id2 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + DROP INDEX idx1, + ADD FULLTEXT INDEX idx2(value); +-affected rows: 0 +-info: Records: 0 Duplicates: 0 Warnings: 0 ++affected rows: 2 ++info: Records: 2 Duplicates: 0 Warnings: 0 + DROP TABLE t1; + SET GLOBAL debug_dbug = @save_debug; diff --git a/mysql-test/suite/innodb_fts/r/sync_ddl.result b/mysql-test/suite/innodb_fts/r/sync_ddl.result index 441954dc77b..5ebe1575d91 100644 --- a/mysql-test/suite/innodb_fts/r/sync_ddl.result +++ b/mysql-test/suite/innodb_fts/r/sync_ddl.result @@ -99,7 +99,8 @@ ALTER TABLE t1 DROP COLUMN id1, ADD COLUMN id2 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, DROP INDEX idx1, -ADD FULLTEXT INDEX idx2(value), -ALGORITHM=INPLACE; +ADD FULLTEXT INDEX idx2(value); +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 DROP TABLE t1; SET GLOBAL debug_dbug = @save_debug; diff --git a/mysql-test/suite/innodb_fts/t/create.test b/mysql-test/suite/innodb_fts/t/create.test index e6a7e993f84..9d88c1eddd4 100644 --- a/mysql-test/suite/innodb_fts/t/create.test +++ b/mysql-test/suite/innodb_fts/t/create.test @@ -131,8 +131,14 @@ ENGINE=InnoDB; CREATE TABLE t1(a INT PRIMARY KEY, b TEXT, FTS_DOC_ID BIGINT UNSIGNED NOT NULL, UNIQUE KEY FTS_DOC_ID_INDEX(FTS_DOC_ID DESC)) ENGINE=InnoDB; SHOW CREATE TABLE t1; +if ($MTR_COMBINATION_ORIG) { --error ER_INNODB_FT_WRONG_DOCID_INDEX ALTER TABLE t1 ADD FULLTEXT INDEX(b), ALGORITHM=INPLACE; +} +if (!$MTR_COMBINATION_ORIG) { +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +ALTER TABLE t1 ADD FULLTEXT INDEX(b), ALGORITHM=INPLACE; +} --error ER_INNODB_FT_WRONG_DOCID_INDEX ALTER TABLE t1 ADD FULLTEXT INDEX(b), ALGORITHM=COPY; DROP TABLE t1; diff --git a/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test b/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test index cef8df2d113..11d2d493bf3 100644 --- a/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test +++ b/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test @@ -20,11 +20,20 @@ INSERT INTO fts_test (title,body) VALUES ('MySQL Security','When configured properly, MySQL ...'); # Table does rebuild when fts index builds for the first time +# Create the FTS index + +if ($MTR_COMBINATION_ORIG) { --error ER_ALTER_OPERATION_NOT_SUPPORTED ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=NOCOPY; - -# Create the FTS index ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=INPLACE; +} +if (!$MTR_COMBINATION_ORIG) { +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=NOCOPY; +--enable_info +ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body); +--disable_info +} # Select word "tutorial" in the table SELECT * FROM fts_test WHERE MATCH (title, body) @@ -43,7 +52,14 @@ INSERT INTO fts_test (title,body) VALUES ('MySQL Security','When configured properly, MySQL ...'); # FTS_DOC_ID hidden column and FTS_DOC_ID index exist +if ($MTR_COMBINATION_ORIG) { ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=NOCOPY; +} +if (!$MTR_COMBINATION_ORIG) { +--enable_info +ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body); +--disable_info +} # Select word "tutorial" in the table SELECT * FROM fts_test WHERE MATCH (title, body) @@ -112,7 +128,14 @@ INSERT INTO fts_test (title,body) VALUES # column already exists. This has not been implemented yet. --error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON CREATE FULLTEXT INDEX idx on fts_test (title, body) LOCK=NONE; +if ($MTR_COMBINATION_ORIG) { ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=NOCOPY; +} +if (!$MTR_COMBINATION_ORIG) { +--enable_info +ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body); +--disable_info +} --error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON ALTER TABLE fts_test ROW_FORMAT=REDUNDANT, LOCK=NONE; @@ -349,8 +372,14 @@ let $fts_aux_file= `select concat('FTS_',right(concat(repeat('0',16), lower(hex( write_file $MYSQLD_DATADIR/test/$fts_aux_file; EOF --replace_regex /".*" from/"Resource temporarily unavailable" from/ +if ($MTR_COMBINATION_ORIG) { --error ER_GET_ERRNO ALTER TABLE t1 ADD FULLTEXT(a), ALGORITHM=INPLACE; +} +if (!$MTR_COMBINATION_ORIG) { +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +ALTER TABLE t1 ADD FULLTEXT(a), ALGORITHM=INPLACE; +} DROP TABLE t1; remove_file $MYSQLD_DATADIR/test/$fts_aux_file; diff --git a/mysql-test/suite/innodb_fts/t/innodb-fts-fic.test b/mysql-test/suite/innodb_fts/t/innodb-fts-fic.test index 2d94c21398c..05855106226 100644 --- a/mysql-test/suite/innodb_fts/t/innodb-fts-fic.test +++ b/mysql-test/suite/innodb_fts/t/innodb-fts-fic.test @@ -211,8 +211,13 @@ INSERT INTO wp (FTS_DOC_ID, title, text) VALUES (1, 'MySQL Tutorial','DBMS stands for DataBase ...'), (2, 'How To Use MySQL Well','After you went through a ...'); +if ($MTR_COMBINATION_ORIG) { --error ER_INNODB_FT_WRONG_DOCID_COLUMN CREATE FULLTEXT INDEX idx ON wp(title, text); +} +if (!$MTR_COMBINATION_ORIG) { +CREATE FULLTEXT INDEX idx ON wp(title, text); +} DROP TABLE wp; CREATE TABLE wp( diff --git a/mysql-test/suite/innodb_fts/t/misc_debug.test b/mysql-test/suite/innodb_fts/t/misc_debug.test index 08581768eec..8e4ec5d9baf 100644 --- a/mysql-test/suite/innodb_fts/t/misc_debug.test +++ b/mysql-test/suite/innodb_fts/t/misc_debug.test @@ -23,8 +23,14 @@ CREATE TABLE articles ( # The newly create dict_index_t should be removed from fts cache SET @saved_debug_dbug = @@SESSION.debug_dbug; SET SESSION debug_dbug="+d,ib_dict_create_index_tree_fail"; +if ($MTR_COMBINATION_ORIG) { --error ER_OUT_OF_RESOURCES CREATE FULLTEXT INDEX idx ON articles(body); +} +if (!$MTR_COMBINATION_ORIG) { +--error ER_CANT_CREATE_TABLE +CREATE FULLTEXT INDEX idx ON articles(body); +} SET SESSION debug_dbug=@saved_debug_dbug; # This simply go through ha_innobase::commit_inplace_alter_table @@ -37,8 +43,14 @@ DROP TABLE articles; CREATE TABLE t (a INT, b TEXT) engine=innodb; SET debug_dbug='+d,alter_table_rollback_new_index'; +if ($MTR_COMBINATION_ORIG) { -- error ER_UNKNOWN_ERROR ALTER TABLE t ADD FULLTEXT INDEX (b(64)); +} +if (!$MTR_COMBINATION_ORIG) { +-- error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +ALTER TABLE t ADD FULLTEXT INDEX (b(64)), ALGORITHM=INPLACE; +} SET SESSION debug_dbug=@saved_debug_dbug; DROP TABLE t; @@ -57,6 +69,7 @@ ALTER TABLE t1 FORCE; DROP TABLE t2, t1; SET SESSION debug_dbug=@saved_debug_dbug; +if ($MTR_COMBINATION_ORIG) { --echo # --echo # MDEV-25200 Index count mismatch due to aborted FULLTEXT INDEX --echo # @@ -82,6 +95,7 @@ ALTER TABLE t1 ADD bl INT AS (LENGTH(b)) VIRTUAL; CHECK TABLE t1; DROP TABLE t1; --source include/wait_until_count_sessions.inc +} --echo # --echo # MDEV-25663 Double free of transaction during TRUNCATE @@ -104,6 +118,7 @@ SET debug_dbug=@saved_debug_dbug; DROP TABLE t1; --echo # End of 10.3 tests +if ($MTR_COMBINATION_ORIG) { # Fulltext fails in commit phase CREATE TABLE t1(f1 INT NOT NULL, f2 CHAR(100))ENGINE=InnoDB; @@ -115,3 +130,4 @@ ALTER TABLE t1 DISCARD TABLESPACE; --error ER_TABLESPACE_DISCARDED ALTER TABLE t1 ADD FULLTEXT(f2); DROP TABLE t1; +} diff --git a/mysql-test/suite/innodb_fts/t/sync_ddl.test b/mysql-test/suite/innodb_fts/t/sync_ddl.test index 6a16ececa60..9a0451e9d38 100644 --- a/mysql-test/suite/innodb_fts/t/sync_ddl.test +++ b/mysql-test/suite/innodb_fts/t/sync_ddl.test @@ -182,12 +182,13 @@ INSERT INTO t1 (value) VALUES ('collation of latin1_bin to make it case sensitive') ; +--enable_info ALTER TABLE t1 DROP COLUMN id1, ADD COLUMN id2 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, DROP INDEX idx1, - ADD FULLTEXT INDEX idx2(value), - ALGORITHM=INPLACE; + ADD FULLTEXT INDEX idx2(value); +--disable_info DROP TABLE t1; 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/mysql-test/suite/mariabackup/rpl_clone_slave.result b/mysql-test/suite/mariabackup/rpl_clone_slave.result new file mode 100644 index 00000000000..2e6c27016f0 --- /dev/null +++ b/mysql-test/suite/mariabackup/rpl_clone_slave.result @@ -0,0 +1,202 @@ +include/master-slave.inc +[connection master] +# +# MDEV-33342 Add a replication MTR test cloning the slave with mariadb-backup +# +connection slave; +stop slave; +change master to master_use_gtid=no; +start slave; +connection master; +connection slave; +############################################################## +### Initial block with some transactions +### Slave: Make sure replication is not using GTID +connection slave; +# Using_Gtid=No +### Master: Create and populate t1 +connection master; +CREATE TABLE t1(a TEXT) ENGINE=InnoDB; +START TRANSACTION; +INSERT INTO t1 VALUES ('tr#00:stmt#00 - slave run#0, before backup'); +INSERT INTO t1 VALUES ('tr#00:stmt#01 - slave run#0, before backup'); +INSERT INTO t1 VALUES ('tr#00:stmt#02 - slave run#0, before backup'); +COMMIT; +connection slave; +############################################################## +### Run the last transaction before mariadb-backup --backup +### Remember SHOW MASTER STATUS and @@gtid_binlog_pos +### before and after the transaction. +### Master: Rember MASTER STATUS and @@gtid_binlog_pos before tr#01 +connection master; +### Slave: Remember MASTER STATUS and @@gtid_binlog_pos before tr#01 +connection slave; +### Master: Run the actual last transaction before the backup +connection master; +START TRANSACTION; +INSERT INTO t1 VALUES ('tr#01:stmt#00 - slave run#0, before backup'); +INSERT INTO t1 VALUES ('tr#01:stmt#01 - slave run#0, before backup'); +INSERT INTO t1 VALUES ('tr#01:stmt#02 - slave run#0, before backup'); +COMMIT; +connection slave; +### Master: Remember MASTER STATUS and @@gtid_binlog_pos after tr#01 +connection master; +### Slave: Remember MASTER STATUS and @@gtid_binlog_pos after tr#01 +connection slave; +############################################################## +### Running `mariadb-backup --backup,--prepare` and checking +### that xtrabackup_slave_info and xtrabackup_binlog_info are OK +### Slave: Create a backup +### Slave: Prepare the backup +### Slave: xtrabackup files: +############################ xtrabackup_slave_info +CHANGE MASTER TO MASTER_LOG_FILE='master_after_tr01_show_master_status_file', MASTER_LOG_POS=master_after_tr01_show_master_status_position; +############################ xtrabackup_binlog_info +slave_after_tr01_show_master_status_file slave_after_tr01_show_master_status_position slave_after_tr01_gtid_binlog_pos +############################ +############################################################## +### Run more transactions after the backup: +### - while the slave is still running, then +### - while the slave is shut down +### Master: Run another transaction while the slave is still running +connection master; +START TRANSACTION; +INSERT INTO t1 VALUES ('tr#02:stmt#00 - slave run#0, after backup'); +INSERT INTO t1 VALUES ('tr#02:stmt#01 - slave run#0, after backup'); +INSERT INTO t1 VALUES ('tr#02:stmt@02 - slave run#0, after backup'); +COMMIT; +connection slave; +### Master: Remember MASTER STATUS and @@gtid_binlog_pos after tr#02 +connection master; +### Slave: Remember MASTER STATUS and @@gtid_binlog_pos after tr#02 +connection slave; +### Master: Checking SHOW BINLOG EVENTS +connection master; +SHOW BINLOG EVENTS IN 'master_after_tr01_show_master_status_file' FROM master_after_tr01_show_master_status_position LIMIT 0,1; +Log_name master_after_tr01_show_master_status_file +Pos master_after_tr01_show_master_status_position +Event_type Gtid +Server_id # +End_log_pos # +Info BEGIN GTID master_after_tr02_gtid_binlog_pos +SHOW BINLOG EVENTS IN 'master_after_tr01_show_master_status_file' FROM master_after_tr01_show_master_status_position LIMIT 1,1; +Log_name master_after_tr01_show_master_status_file +Pos # +Event_type Query_or_Annotate_rows +Server_id # +End_log_pos # +Info INSERT INTO t1 VALUES ('tr#02:stmt#00 - slave run#0, after backup') +### Slave: Checking SHOW BINLOG EVENTS +connection slave; +SHOW BINLOG EVENTS IN 'slave_after_tr01_show_master_status_file' FROM slave_after_tr01_show_master_status_position LIMIT 0,1; +Log_name slave_after_tr01_show_master_status_file +Pos # +Event_type Gtid +Server_id 1 +End_log_pos # +Info BEGIN GTID slave_after_tr02_gtid_binlog_pos +SHOW BINLOG EVENTS IN 'slave_after_tr01_show_master_status_file' FROM slave_after_tr01_show_master_status_position LIMIT 1,1; +Log_name slave_after_tr01_show_master_status_file +Pos # +Event_type Query_or_Annotate_rows +Server_id # +End_log_pos # +Info INSERT INTO t1 VALUES ('tr#02:stmt#00 - slave run#0, after backup') +### Slave: Stop replication +connection slave; +STOP SLAVE; +include/wait_for_slave_to_stop.inc +RESET SLAVE; +Warnings: +Note 4190 RESET SLAVE is implicitly changing the value of 'Using_Gtid' from 'No' to 'Slave_Pos' +### Slave: Shutdown the server +include/rpl_stop_server.inc [server_number=2] +### Master: Run a transaction while the slave is shut down +connection master; +START TRANSACTION; +INSERT INTO t1 VALUES ('tr#03:stmt#00 - after slave run#0, slave is shut down, after backup'); +INSERT INTO t1 VALUES ('tr#03:stmt#01 - after slave run#0, slave is shut down, after backup'); +INSERT INTO t1 VALUES ('tr#03:stmt#02 - after slave run#0, slave is shut down, after backup'); +COMMIT; +############################################################## +### Emulate starting a new virgin slave +### Slave: Remove the data directory +### Slave: Copy back the backup +### Slave: Restart the server +include/rpl_start_server.inc [server_number=2] +### Slave: Display the restored data before START SLAVE +connection slave; +SELECT * FROM t1 ORDER BY a; +a +tr#00:stmt#00 - slave run#0, before backup +tr#00:stmt#01 - slave run#0, before backup +tr#00:stmt#02 - slave run#0, before backup +tr#01:stmt#00 - slave run#0, before backup +tr#01:stmt#01 - slave run#0, before backup +tr#01:stmt#02 - slave run#0, before backup +### Slave: Execute the CHANGE MASTER statement to set up the host and port +CHANGE MASTER '' TO MASTER_USER='root', MASTER_HOST='127.0.0.1', MASTER_PORT=###, MASTER_CONNECT_RETRY=1; +### Slave: Execute the CHANGE MASTER statement from xtrabackup_slave_info +CHANGE MASTER TO MASTER_LOG_FILE='master_after_tr01_show_master_status_file', MASTER_LOG_POS=master_after_tr01_show_master_status_position; +Warnings: +Note 4190 CHANGE MASTER TO is implicitly changing the value of 'Using_Gtid' from 'Slave_Pos' to 'No' +### Slave: Execute START SLAVE +include/start_slave.inc +### Master: Wait for the slave to apply all master events +connection master; +connection slave; +### Slave: Make sure replication is not using GTID after the slave restart +connection slave; +# Using_Gtid=No +### Slave: Display the restored data after START SLAVE +connection slave; +SELECT * FROM t1 ORDER BY a; +a +tr#00:stmt#00 - slave run#0, before backup +tr#00:stmt#01 - slave run#0, before backup +tr#00:stmt#02 - slave run#0, before backup +tr#01:stmt#00 - slave run#0, before backup +tr#01:stmt#01 - slave run#0, before backup +tr#01:stmt#02 - slave run#0, before backup +tr#02:stmt#00 - slave run#0, after backup +tr#02:stmt#01 - slave run#0, after backup +tr#02:stmt@02 - slave run#0, after backup +tr#03:stmt#00 - after slave run#0, slave is shut down, after backup +tr#03:stmt#01 - after slave run#0, slave is shut down, after backup +tr#03:stmt#02 - after slave run#0, slave is shut down, after backup +############################################################## +### Continue master transactions, check the new slave replicates well. +### Master: Run a transaction after restarting replication +connection master; +START TRANSACTION; +INSERT INTO t1 VALUES ('tr#04:stmt#00 - slave run#1'); +INSERT INTO t1 VALUES ('tr#04:stmt#01 - slave run#1'); +INSERT INTO t1 VALUES ('tr#04:stmt#02 - slave run#1'); +COMMIT; +connection slave; +### Slave: Display the restored data + new transactions +connection slave; +SELECT * FROM t1 ORDER BY a; +a +tr#00:stmt#00 - slave run#0, before backup +tr#00:stmt#01 - slave run#0, before backup +tr#00:stmt#02 - slave run#0, before backup +tr#01:stmt#00 - slave run#0, before backup +tr#01:stmt#01 - slave run#0, before backup +tr#01:stmt#02 - slave run#0, before backup +tr#02:stmt#00 - slave run#0, after backup +tr#02:stmt#01 - slave run#0, after backup +tr#02:stmt@02 - slave run#0, after backup +tr#03:stmt#00 - after slave run#0, slave is shut down, after backup +tr#03:stmt#01 - after slave run#0, slave is shut down, after backup +tr#03:stmt#02 - after slave run#0, slave is shut down, after backup +tr#04:stmt#00 - slave run#1 +tr#04:stmt#01 - slave run#1 +tr#04:stmt#02 - slave run#1 +############################################################## +### Cleanup +### Removing the backup directory +connection master; +DROP TABLE t1; +connection slave; +include/rpl_end.inc diff --git a/mysql-test/suite/mariabackup/rpl_clone_slave.test b/mysql-test/suite/mariabackup/rpl_clone_slave.test new file mode 100644 index 00000000000..7d93f72327f --- /dev/null +++ b/mysql-test/suite/mariabackup/rpl_clone_slave.test @@ -0,0 +1,17 @@ +# +# Cloning a slave using mariadb-backup +# +--source include/have_innodb.inc +--source include/master-slave.inc + +--echo # +--echo # MDEV-33342 Add a replication MTR test cloning the slave with mariadb-backup +--echo # + +connection slave; +stop slave; +change master to master_use_gtid=no; +start slave; + +--let cnf=mariadb_to_mariadb +--source include/rpl_clone_slave_using_mariadb-backup.inc diff --git a/mysql-test/suite/mariabackup/suite.opt b/mysql-test/suite/mariabackup/suite.opt index 1df4643562e..e6b20c328b2 100644 --- a/mysql-test/suite/mariabackup/suite.opt +++ b/mysql-test/suite/mariabackup/suite.opt @@ -1 +1 @@ ---innodb --loose-changed_page_bitmaps --innodb-sys-tables --innodb-flush-log-at-trx-commit=2 --sequence +--innodb --innodb-sys-tables --innodb-flush-log-at-trx-commit=2 --sequence diff --git a/mysql-test/suite/parts/r/partition_alter4_innodb.result b/mysql-test/suite/parts/r/partition_alter4_innodb.result index aab121f2b23..d4efb87a59c 100644 --- a/mysql-test/suite/parts/r/partition_alter4_innodb.result +++ b/mysql-test/suite/parts/r/partition_alter4_innodb.result @@ -60,7 +60,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -521,7 +520,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -993,7 +991,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -1466,7 +1463,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -1933,7 +1929,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -2406,7 +2401,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -2884,7 +2878,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -3360,7 +3353,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -3826,7 +3818,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -4287,7 +4278,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -4759,7 +4749,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -5232,7 +5221,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -5699,7 +5687,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -6172,7 +6159,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -6650,7 +6636,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -7126,7 +7111,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -15108,7 +15092,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -15569,7 +15552,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -16041,7 +16023,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -16514,7 +16495,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -16981,7 +16961,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -17454,7 +17433,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -17932,7 +17910,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -18408,7 +18385,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template diff --git a/mysql-test/suite/parts/r/partition_alter4_myisam.result b/mysql-test/suite/parts/r/partition_alter4_myisam.result index c863d479fbb..3c06585e93a 100644 --- a/mysql-test/suite/parts/r/partition_alter4_myisam.result +++ b/mysql-test/suite/parts/r/partition_alter4_myisam.result @@ -60,7 +60,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -530,7 +529,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -1017,7 +1015,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -1511,7 +1508,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -1995,7 +1991,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -2489,7 +2484,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -2988,7 +2982,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -3485,7 +3478,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -3974,7 +3966,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -4444,7 +4435,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -4931,7 +4921,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -5425,7 +5414,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -5909,7 +5897,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -6403,7 +6390,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -6902,7 +6888,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -7399,7 +7384,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -15700,7 +15684,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -16170,7 +16153,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -16657,7 +16639,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -17151,7 +17132,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -17635,7 +17615,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -18129,7 +18108,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -18628,7 +18606,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -19125,7 +19102,6 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template diff --git a/mysql-test/suite/parts/r/partition_mgm_lc0_innodb.result b/mysql-test/suite/parts/r/partition_mgm_lc0_innodb.result index 88784224723..28dcddd9aef 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc0_innodb.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc0_innodb.result @@ -1020,7 +1020,6 @@ a b 2001 Second in MAX ALTER TABLE t1 ANALYZE PARTITION MAX; Table Op Msg_type Msg_text -MySQL_Test_DB.t1 analyze status Engine-independent statistics collected MySQL_Test_DB.t1 analyze status OK # Truncate without FLUSH ALTER TABLE t1 TRUNCATE PARTITION MAX; diff --git a/mysql-test/suite/parts/r/partition_mgm_lc0_memory.result b/mysql-test/suite/parts/r/partition_mgm_lc0_memory.result index 92457a21043..204ef94da6e 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc0_memory.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc0_memory.result @@ -1020,7 +1020,6 @@ a b 2001 Second in MAX ALTER TABLE t1 ANALYZE PARTITION MAX; Table Op Msg_type Msg_text -MySQL_Test_DB.t1 analyze status Engine-independent statistics collected MySQL_Test_DB.t1 analyze note The storage engine for the table doesn't support analyze # Truncate without FLUSH ALTER TABLE t1 TRUNCATE PARTITION MAX; diff --git a/mysql-test/suite/parts/r/partition_mgm_lc0_myisam.result b/mysql-test/suite/parts/r/partition_mgm_lc0_myisam.result index fea80a3feb3..10f8fbe11a4 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc0_myisam.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc0_myisam.result @@ -1020,7 +1020,6 @@ a b 2001 Second in MAX ALTER TABLE t1 ANALYZE PARTITION MAX; Table Op Msg_type Msg_text -MySQL_Test_DB.t1 analyze status Engine-independent statistics collected MySQL_Test_DB.t1 analyze status OK # Truncate without FLUSH ALTER TABLE t1 TRUNCATE PARTITION MAX; diff --git a/mysql-test/suite/parts/r/partition_mgm_lc1_innodb.result b/mysql-test/suite/parts/r/partition_mgm_lc1_innodb.result index 418650eb438..d9b677acf5a 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc1_innodb.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc1_innodb.result @@ -987,7 +987,6 @@ a b 2001 Second in MAX ALTER TABLE t1 ANALYZE PARTITION MAX; Table Op Msg_type Msg_text -mysql_test_db.t1 analyze status Engine-independent statistics collected mysql_test_db.t1 analyze status OK # Truncate without FLUSH ALTER TABLE t1 TRUNCATE PARTITION MAX; diff --git a/mysql-test/suite/parts/r/partition_mgm_lc1_memory.result b/mysql-test/suite/parts/r/partition_mgm_lc1_memory.result index 96e72cbfb41..601f6cb7812 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc1_memory.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc1_memory.result @@ -987,7 +987,6 @@ a b 2001 Second in MAX ALTER TABLE t1 ANALYZE PARTITION MAX; Table Op Msg_type Msg_text -mysql_test_db.t1 analyze status Engine-independent statistics collected mysql_test_db.t1 analyze note The storage engine for the table doesn't support analyze # Truncate without FLUSH ALTER TABLE t1 TRUNCATE PARTITION MAX; diff --git a/mysql-test/suite/parts/r/partition_mgm_lc1_myisam.result b/mysql-test/suite/parts/r/partition_mgm_lc1_myisam.result index 0ab07cdc993..936f972ddb8 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc1_myisam.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc1_myisam.result @@ -987,7 +987,6 @@ a b 2001 Second in MAX ALTER TABLE t1 ANALYZE PARTITION MAX; Table Op Msg_type Msg_text -mysql_test_db.t1 analyze status Engine-independent statistics collected mysql_test_db.t1 analyze status OK # Truncate without FLUSH ALTER TABLE t1 TRUNCATE PARTITION MAX; diff --git a/mysql-test/suite/period/r/overlaps.result b/mysql-test/suite/period/r/overlaps.result index 78b1ac18b8d..36a9086f02b 100644 --- a/mysql-test/suite/period/r/overlaps.result +++ b/mysql-test/suite/period/r/overlaps.result @@ -449,3 +449,85 @@ VALUES ('2000-01-01 00:00:00.000000', '2001-01-01 00:00:00.000000', 'abc'); ERROR 23000: Duplicate entry 'abc-2001-01-01 00:00:00.000000-2000-01-01 00:00:00.000000' for key 'index_name' DROP TABLE t1; +# MDEV-25370 Update for portion changes autoincrement key in period table +create or replace table cars(id int auto_increment, +price int, s date, e date, +period for p(s,e), +primary key(id, p without overlaps)); +insert into cars(price, s, e) values (1000, '2018-01-01', '2020-01-01'); +select * from cars; +id price s e +1 1000 2018-01-01 2020-01-01 +update cars for portion of p from '2019-01-01' to '2019-12-01' set price= 1100; +select * from cars; +id price s e +1 1000 2018-01-01 2019-01-01 +1 1000 2019-12-01 2020-01-01 +1 1100 2019-01-01 2019-12-01 +delete from cars for portion of p from '2019-12-10' to '2019-12-20'; +select * from cars; +id price s e +1 1000 2018-01-01 2019-01-01 +1 1000 2019-12-01 2019-12-10 +1 1000 2019-12-20 2020-01-01 +1 1100 2019-01-01 2019-12-01 +# AUTO_INCREMENT field is separate from WITHOUT OVERLAPS +create or replace table cars(id int primary key auto_increment, +car_id int, +price int, s date, e date, +period for p(s,e), +unique(car_id, p without overlaps)); +insert cars(car_id, price, s, e) values (1, 1000, '2018-01-01', '2020-01-01'); +select * from cars; +id car_id price s e +1 1 1000 2018-01-01 2020-01-01 +update cars for portion of p from '2019-01-01' to '2019-12-01' set price= 1100; +select * from cars; +id car_id price s e +1 1 1100 2019-01-01 2019-12-01 +2 1 1000 2018-01-01 2019-01-01 +3 1 1000 2019-12-01 2020-01-01 +delete from cars for portion of p from '2019-12-10' to '2019-12-20'; +select * from cars; +id car_id price s e +1 1 1100 2019-01-01 2019-12-01 +2 1 1000 2018-01-01 2019-01-01 +4 1 1000 2019-12-01 2019-12-10 +5 1 1000 2019-12-20 2020-01-01 +# AUTO_INCREMENT field is both standalone and in WITHOUT OVERLAPS +create or replace table cars(id int primary key auto_increment, +price int, s date, e date, +period for p(s,e), +unique(id, p without overlaps)); +insert cars(price, s, e) values (1000, '2018-01-01', '2020-01-01'); +insert cars(price, s, e) values (1000, '2021-01-01', '2022-01-01'); +update cars for portion of p from '2019-01-01' to '2019-12-01' set price= 1100; +# autoincrement index is: id int primary key +# id increments each time. +select * from cars; +id price s e +1 1100 2019-01-01 2019-12-01 +2 1000 2021-01-01 2022-01-01 +3 1000 2018-01-01 2019-01-01 +4 1000 2019-12-01 2020-01-01 +truncate cars; +insert cars(price, s, e) values (1000, '2018-01-01', '2020-01-01'); +delete from cars for portion of p from '2019-12-10' to '2019-12-20'; +select * from cars; +id price s e +2 1000 2018-01-01 2019-12-10 +3 1000 2019-12-20 2020-01-01 +create or replace table cars(id int unique auto_increment, +price int, s date, e date, +period for p(s,e), +primary key (id, p without overlaps)); +insert cars(price, s, e) values (1000, '2018-01-01', '2020-01-01'); +# autoincrement index is: primary key (id, p without overlaps) +# id is not incremented, hence duplication error +update cars for portion of p from '2019-01-01' to '2019-12-01' set price= 1100; +ERROR 23000: Duplicate entry '1' for key 'id' +truncate cars; +insert cars(price, s, e) values (1000, '2018-01-01', '2020-01-01'); +delete from cars for portion of p from '2019-12-10' to '2019-12-20'; +ERROR 23000: Duplicate entry '1' for key 'id' +drop table cars; diff --git a/mysql-test/suite/period/t/overlaps.test b/mysql-test/suite/period/t/overlaps.test index 4e71d64d595..b762743be24 100644 --- a/mysql-test/suite/period/t/overlaps.test +++ b/mysql-test/suite/period/t/overlaps.test @@ -458,3 +458,80 @@ VALUES ('2000-01-01 00:00:00.000000', '2001-01-01 00:00:00.000000', 'abc '), ('2000-01-01 00:00:00.000000', '2001-01-01 00:00:00.000000', 'abc'); DROP TABLE t1; + +--echo # MDEV-25370 Update for portion changes autoincrement key in period table +create or replace table cars(id int auto_increment, + price int, s date, e date, + period for p(s,e), + primary key(id, p without overlaps)); + +insert into cars(price, s, e) values (1000, '2018-01-01', '2020-01-01'); +select * from cars; + +update cars for portion of p from '2019-01-01' to '2019-12-01' set price= 1100; +--sorted_result +select * from cars; + +delete from cars for portion of p from '2019-12-10' to '2019-12-20'; +--sorted_result +select * from cars; + +--echo # AUTO_INCREMENT field is separate from WITHOUT OVERLAPS +create or replace table cars(id int primary key auto_increment, + car_id int, + price int, s date, e date, + period for p(s,e), + unique(car_id, p without overlaps)); + +insert cars(car_id, price, s, e) values (1, 1000, '2018-01-01', '2020-01-01'); +select * from cars; + +update cars for portion of p from '2019-01-01' to '2019-12-01' set price= 1100; +--sorted_result +select * from cars; + +delete from cars for portion of p from '2019-12-10' to '2019-12-20'; +--sorted_result +select * from cars; + + +--echo # AUTO_INCREMENT field is both standalone and in WITHOUT OVERLAPS +create or replace table cars(id int primary key auto_increment, + price int, s date, e date, + period for p(s,e), + unique(id, p without overlaps)); + +insert cars(price, s, e) values (1000, '2018-01-01', '2020-01-01'); +insert cars(price, s, e) values (1000, '2021-01-01', '2022-01-01'); + +update cars for portion of p from '2019-01-01' to '2019-12-01' set price= 1100; +--echo # autoincrement index is: id int primary key +--echo # id increments each time. +--sorted_result +select * from cars; + +truncate cars; +insert cars(price, s, e) values (1000, '2018-01-01', '2020-01-01'); + +delete from cars for portion of p from '2019-12-10' to '2019-12-20'; +--sorted_result +select * from cars; + +create or replace table cars(id int unique auto_increment, + price int, s date, e date, + period for p(s,e), + primary key (id, p without overlaps)); + +insert cars(price, s, e) values (1000, '2018-01-01', '2020-01-01'); +--echo # autoincrement index is: primary key (id, p without overlaps) +--echo # id is not incremented, hence duplication error +--error ER_DUP_ENTRY +update cars for portion of p from '2019-01-01' to '2019-12-01' set price= 1100; + +truncate cars; +insert cars(price, s, e) values (1000, '2018-01-01', '2020-01-01'); + +--error ER_DUP_ENTRY +delete from cars for portion of p from '2019-12-10' to '2019-12-20'; + +drop table cars; diff --git a/mysql-test/suite/plugins/r/compression,innodb-lz4.rdiff b/mysql-test/suite/plugins/r/compression,innodb-lz4.rdiff index 791aecda080..00abc19647c 100644 --- a/mysql-test/suite/plugins/r/compression,innodb-lz4.rdiff +++ b/mysql-test/suite/plugins/r/compression,innodb-lz4.rdiff @@ -18,11 +18,11 @@ -# restart: --disable-provider-bzip2 +# restart: --disable-provider-lz4 select a, left(b, 9), length(b) from t1; - ERROR 42S02: Table 'test.t1' doesn't exist in engine + ERROR HY000: Table `test`.`t1` is corrupted. Please drop the table and recreate. show warnings; Level Code Message -Warning 4185 MariaDB tried to use the BZip2 compression, but its provider plugin is not loaded +Warning 4185 MariaDB tried to use the LZ4 compression, but its provider plugin is not loaded - Error 1932 Table 'test.t1' doesn't exist in engine + Error 1877 Table `test`.`t1` is corrupted. Please drop the table and recreate. drop table t1; # restart diff --git a/mysql-test/suite/plugins/r/compression,innodb-lzma.rdiff b/mysql-test/suite/plugins/r/compression,innodb-lzma.rdiff index 13c42f82b43..0119adc7482 100644 --- a/mysql-test/suite/plugins/r/compression,innodb-lzma.rdiff +++ b/mysql-test/suite/plugins/r/compression,innodb-lzma.rdiff @@ -18,11 +18,11 @@ -# restart: --disable-provider-bzip2 +# restart: --disable-provider-lzma select a, left(b, 9), length(b) from t1; - ERROR 42S02: Table 'test.t1' doesn't exist in engine + ERROR HY000: Table `test`.`t1` is corrupted. Please drop the table and recreate. show warnings; Level Code Message -Warning 4185 MariaDB tried to use the BZip2 compression, but its provider plugin is not loaded +Warning 4185 MariaDB tried to use the LZMA compression, but its provider plugin is not loaded - Error 1932 Table 'test.t1' doesn't exist in engine + Error 1877 Table `test`.`t1` is corrupted. Please drop the table and recreate. drop table t1; # restart diff --git a/mysql-test/suite/plugins/r/compression,innodb-lzo.rdiff b/mysql-test/suite/plugins/r/compression,innodb-lzo.rdiff index cc7783cc4f8..52a794a99d7 100644 --- a/mysql-test/suite/plugins/r/compression,innodb-lzo.rdiff +++ b/mysql-test/suite/plugins/r/compression,innodb-lzo.rdiff @@ -18,11 +18,11 @@ -# restart: --disable-provider-bzip2 +# restart: --disable-provider-lzo select a, left(b, 9), length(b) from t1; - ERROR 42S02: Table 'test.t1' doesn't exist in engine + ERROR HY000: Table `test`.`t1` is corrupted. Please drop the table and recreate. show warnings; Level Code Message -Warning 4185 MariaDB tried to use the BZip2 compression, but its provider plugin is not loaded +Warning 4185 MariaDB tried to use the LZO compression, but its provider plugin is not loaded - Error 1932 Table 'test.t1' doesn't exist in engine + Error 1877 Table `test`.`t1` is corrupted. Please drop the table and recreate. drop table t1; # restart diff --git a/mysql-test/suite/plugins/r/compression,innodb-snappy.rdiff b/mysql-test/suite/plugins/r/compression,innodb-snappy.rdiff index 98c4427a758..cbbd754aa17 100644 --- a/mysql-test/suite/plugins/r/compression,innodb-snappy.rdiff +++ b/mysql-test/suite/plugins/r/compression,innodb-snappy.rdiff @@ -18,11 +18,11 @@ -# restart: --disable-provider-bzip2 +# restart: --disable-provider-snappy select a, left(b, 9), length(b) from t1; - ERROR 42S02: Table 'test.t1' doesn't exist in engine + ERROR HY000: Table `test`.`t1` is corrupted. Please drop the table and recreate. show warnings; Level Code Message -Warning 4185 MariaDB tried to use the BZip2 compression, but its provider plugin is not loaded +Warning 4185 MariaDB tried to use the Snappy compression, but its provider plugin is not loaded - Error 1932 Table 'test.t1' doesn't exist in engine + Error 1877 Table `test`.`t1` is corrupted. Please drop the table and recreate. drop table t1; # restart diff --git a/mysql-test/suite/plugins/r/compression,mroonga-lz4.rdiff b/mysql-test/suite/plugins/r/compression,mroonga-lz4.rdiff index ac186d3c566..3f449220df5 100644 --- a/mysql-test/suite/plugins/r/compression,mroonga-lz4.rdiff +++ b/mysql-test/suite/plugins/r/compression,mroonga-lz4.rdiff @@ -23,11 +23,11 @@ -# restart: --disable-provider-bzip2 +# restart: --disable-provider-lz4 select a, left(b, 9), length(b) from t1; --ERROR 42S02: Table 'test.t1' doesn't exist in engine +-ERROR HY000: Table `test`.`t1` is corrupted. Please drop the table and recreate. -show warnings; -Level Code Message -Warning 4185 MariaDB tried to use the BZip2 compression, but its provider plugin is not loaded --Error 1932 Table 'test.t1' doesn't exist in engine +-Error 1877 Table `test`.`t1` is corrupted. Please drop the table and recreate. +a left(b, 9) length(b) +0 0 +1 0 diff --git a/mysql-test/suite/plugins/r/compression.result b/mysql-test/suite/plugins/r/compression.result index d7c11abc95b..07bfbc0b9bb 100644 --- a/mysql-test/suite/plugins/r/compression.result +++ b/mysql-test/suite/plugins/r/compression.result @@ -18,10 +18,10 @@ a left(b, 9) length(b) 2 ghighighi 30000 # restart: --disable-provider-bzip2 select a, left(b, 9), length(b) from t1; -ERROR 42S02: Table 'test.t1' doesn't exist in engine +ERROR HY000: Table `test`.`t1` is corrupted. Please drop the table and recreate. show warnings; Level Code Message Warning 4185 MariaDB tried to use the BZip2 compression, but its provider plugin is not loaded -Error 1932 Table 'test.t1' doesn't exist in engine +Error 1877 Table `test`.`t1` is corrupted. Please drop the table and recreate. drop table t1; # restart diff --git a/mysql-test/suite/plugins/t/compression.test b/mysql-test/suite/plugins/t/compression.test index df892acfdc4..95ae2df9462 100644 --- a/mysql-test/suite/plugins/t/compression.test +++ b/mysql-test/suite/plugins/t/compression.test @@ -40,7 +40,7 @@ let $restart_parameters = --disable-provider-$alg; source include/restart_mysqld.inc; if ($engine == "innodb") { - error ER_NO_SUCH_TABLE_IN_ENGINE; + error ER_TABLE_CORRUPT; select a, left(b, 9), length(b) from t1; show warnings; } diff --git a/mysql-test/suite/rpl/r/rpl_change_master_demote.result b/mysql-test/suite/rpl/r/rpl_change_master_demote.result index 70d141eff92..2114ac4a208 100644 --- a/mysql-test/suite/rpl/r/rpl_change_master_demote.result +++ b/mysql-test/suite/rpl/r/rpl_change_master_demote.result @@ -683,6 +683,23 @@ connection master; CHANGE MASTER TO master_host='127.0.0.1', master_port=SLAVE_PORT, master_user='root', master_use_gtid=Slave_Pos, master_demote_to_slave=invalid; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'invalid' at line 1 # +# MDEV-31768 +# Ensure MASTER_DEMOTE_TO_REPLICA aliases MASTER_DEMOTE_TO_SLAVE +# +connection slave; +RESET MASTER; +include/reset_slave.inc +CREATE TABLE t_mdev_31768 (a int); +CHANGE MASTER TO master_use_gtid=Replica_Pos, master_demote_to_replica=1; +# Validating alias MASTER_DEMOTE_TO_REPLICA provides intended behavior.. +# ..success +DROP TABLE t_mdev_31768; +RESET MASTER; +include/reset_slave.inc +# Clear primary binlog state to match replica +connection master; +RESET MASTER; +# # Cleanup # connection master; diff --git a/mysql-test/suite/rpl/r/rpl_domain_id_filter_io_crash.result b/mysql-test/suite/rpl/r/rpl_domain_id_filter_io_crash.result index 5250c4bb36a..9d3b2ccdab7 100644 --- a/mysql-test/suite/rpl/r/rpl_domain_id_filter_io_crash.result +++ b/mysql-test/suite/rpl/r/rpl_domain_id_filter_io_crash.result @@ -11,6 +11,7 @@ SELECT * FROM t1; i 1 connection slave; +include/save_master_gtid.inc connection slave; call mtr.add_suppression("Slave I/O: Relay log write failure: could not queue event from master.*"); # Case 0 : Start slave with IGNORE_DOMAIN_IDS=(), then restart @@ -24,6 +25,7 @@ DO_DOMAIN_IDS (BEFORE) : IGNORE_DOMAIN_IDS (BEFORE) : CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos; include/start_slave.inc +include/sync_with_master_gtid.inc DO_DOMAIN_IDS (AFTER) : IGNORE_DOMAIN_IDS (AFTER) : SET @saved_dbug = @@GLOBAL.debug_dbug; @@ -33,6 +35,7 @@ START TRANSACTION; INSERT INTO t1 VALUES(2); INSERT INTO t1 VALUES(3); COMMIT; +include/save_master_gtid.inc SELECT * FROM t1; i 1 @@ -46,6 +49,7 @@ i SET @@global.debug_dbug=@saved_dbug; START SLAVE io_thread; include/wait_for_slave_io_to_start.inc +include/sync_with_master_gtid.inc SELECT * FROM t1; i 1 @@ -59,6 +63,7 @@ DO_DOMAIN_IDS (BEFORE) : IGNORE_DOMAIN_IDS (BEFORE) : CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; include/start_slave.inc +include/sync_with_master_gtid.inc DO_DOMAIN_IDS (AFTER) : IGNORE_DOMAIN_IDS (AFTER) : 1 SET @@global.debug_dbug="d,kill_slave_io_before_commit"; @@ -67,6 +72,7 @@ START TRANSACTION; INSERT INTO t1 VALUES(4); INSERT INTO t1 VALUES(5); COMMIT; +include/save_master_gtid.inc SELECT * FROM t1; i 1 @@ -84,6 +90,7 @@ i SET @@global.debug_dbug=@saved_dbug; START SLAVE io_thread; include/wait_for_slave_io_to_start.inc +include/sync_with_master_gtid.inc SELECT * FROM t1; i 1 @@ -97,6 +104,7 @@ DO_DOMAIN_IDS (BEFORE) : IGNORE_DOMAIN_IDS (BEFORE) : 1 CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos; include/start_slave.inc +include/sync_with_master_gtid.inc DO_DOMAIN_IDS (AFTER) : IGNORE_DOMAIN_IDS (AFTER) : SET @@global.debug_dbug="d,kill_slave_io_before_commit"; @@ -114,6 +122,7 @@ START TRANSACTION; INSERT INTO t1 VALUES(10); INSERT INTO t1 VALUES(11); COMMIT; +include/save_master_gtid.inc SELECT * FROM t1; i 1 @@ -140,6 +149,7 @@ DO_DOMAIN_IDS (BEFORE) : IGNORE_DOMAIN_IDS (BEFORE) : CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; include/start_slave.inc +include/sync_with_master_gtid.inc DO_DOMAIN_IDS (AFTER) : IGNORE_DOMAIN_IDS (AFTER) : 1 SELECT * FROM t1; @@ -157,6 +167,7 @@ DO_DOMAIN_IDS (BEFORE) : IGNORE_DOMAIN_IDS (BEFORE) : 1 CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; include/start_slave.inc +include/sync_with_master_gtid.inc DO_DOMAIN_IDS (AFTER) : IGNORE_DOMAIN_IDS (AFTER) : 1 SET @@global.debug_dbug="d,kill_slave_io_before_commit"; @@ -166,6 +177,7 @@ START TRANSACTION; INSERT INTO t1 VALUES(12); INSERT INTO t1 VALUES(13); COMMIT; +include/save_master_gtid.inc START TRANSACTION; INSERT INTO t1 VALUES(14); INSERT INTO t1 VALUES(15); @@ -204,11 +216,16 @@ i 10 11 SET @@global.debug_dbug=@saved_dbug; +include/sync_with_master_gtid.inc include/stop_slave_sql.inc DO_DOMAIN_IDS (BEFORE) : IGNORE_DOMAIN_IDS (BEFORE) : 1 CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos; +connection master; +include/save_master_gtid.inc +connection slave; include/start_slave.inc +include/sync_with_master_gtid.inc DO_DOMAIN_IDS (AFTER) : IGNORE_DOMAIN_IDS (AFTER) : SELECT * FROM t1; @@ -230,6 +247,7 @@ DO_DOMAIN_IDS (BEFORE) : IGNORE_DOMAIN_IDS (BEFORE) : CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; include/start_slave.inc +include/sync_with_master_gtid.inc DO_DOMAIN_IDS (AFTER) : IGNORE_DOMAIN_IDS (AFTER) : 1 SET @@global.debug_dbug="d,kill_slave_io_after_2_events"; @@ -239,6 +257,7 @@ START TRANSACTION; INSERT INTO t1 VALUES(18); INSERT INTO t1 VALUES(19); COMMIT; +include/save_master_gtid.inc START TRANSACTION; INSERT INTO t1 VALUES(20); INSERT INTO t1 VALUES(21); @@ -287,11 +306,16 @@ i 16 17 SET @@global.debug_dbug=@saved_dbug; +include/sync_with_master_gtid.inc include/stop_slave_sql.inc DO_DOMAIN_IDS (BEFORE) : IGNORE_DOMAIN_IDS (BEFORE) : 1 CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos; +connection master; +include/save_master_gtid.inc +connection slave; include/start_slave.inc +include/sync_with_master_gtid.inc DO_DOMAIN_IDS (AFTER) : IGNORE_DOMAIN_IDS (AFTER) : SELECT * FROM t1; @@ -317,6 +341,7 @@ DO_DOMAIN_IDS (BEFORE) : IGNORE_DOMAIN_IDS (BEFORE) : CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos; include/start_slave.inc +include/sync_with_master_gtid.inc DO_DOMAIN_IDS (AFTER) : IGNORE_DOMAIN_IDS (AFTER) : SET @@global.debug_dbug="d,kill_slave_io_after_2_events"; @@ -335,6 +360,7 @@ START TRANSACTION; INSERT INTO t1 VALUES(28); INSERT INTO t1 VALUES(29); COMMIT; +include/save_master_gtid.inc SELECT * FROM t1; i 1 @@ -389,6 +415,7 @@ DO_DOMAIN_IDS (BEFORE) : IGNORE_DOMAIN_IDS (BEFORE) : CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; include/start_slave.inc +include/sync_with_master_gtid.inc DO_DOMAIN_IDS (AFTER) : IGNORE_DOMAIN_IDS (AFTER) : 1 SELECT * FROM t1; diff --git a/mysql-test/suite/rpl/r/rpl_mark_optimize_tbl_ddl.result b/mysql-test/suite/rpl/r/rpl_mark_optimize_tbl_ddl.result index 9aa31a73e49..09edd28827b 100644 --- a/mysql-test/suite/rpl/r/rpl_mark_optimize_tbl_ddl.result +++ b/mysql-test/suite/rpl/r/rpl_mark_optimize_tbl_ddl.result @@ -55,7 +55,6 @@ PARTITION pmax VALUES LESS THAN (MAXVALUE)); INSERT INTO t1 VALUES (1), (10), (100), (1000); ALTER TABLE t1 ANALYZE PARTITION p0; Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK ALTER TABLE t1 OPTIMIZE PARTITION p0; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_shutdown_await_ack.result b/mysql-test/suite/rpl/r/rpl_semi_sync_shutdown_await_ack.result index 394a7acad41..ebd67c947f0 100644 --- a/mysql-test/suite/rpl/r/rpl_semi_sync_shutdown_await_ack.result +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_shutdown_await_ack.result @@ -15,11 +15,15 @@ call mtr.add_suppression("reply failed"); call mtr.add_suppression("Replication event checksum verification"); call mtr.add_suppression("Relay log write failure"); call mtr.add_suppression("Failed to kill the active semi-sync connection"); +set @sav_enabled_server_2= @@GLOBAL.rpl_semi_sync_slave_enabled; +set @sav_server_2_dbug= @@GLOBAL.debug_dbug; connection server_3; call mtr.add_suppression("reply failed"); call mtr.add_suppression("Replication event checksum verification"); call mtr.add_suppression("Relay log write failure"); call mtr.add_suppression("Failed to kill the active semi-sync connection"); +set @sav_enabled_server_3= @@GLOBAL.rpl_semi_sync_slave_enabled; +set @sav_server_3_dbug= @@GLOBAL.debug_dbug; connection server_1; CREATE TABLE t1 (a int); connection server_2; @@ -40,15 +44,15 @@ connection server_1; #-- Enable semi-sync on slaves let slave_last= 3 connection server_2; -set global rpl_semi_sync_slave_enabled = 1; include/stop_slave.inc +set global rpl_semi_sync_slave_enabled = 1; include/start_slave.inc show status like 'Rpl_semi_sync_slave_status'; Variable_name Value Rpl_semi_sync_slave_status ON connection server_3; -set global rpl_semi_sync_slave_enabled = 1; include/stop_slave.inc +set global rpl_semi_sync_slave_enabled = 1; include/start_slave.inc show status like 'Rpl_semi_sync_slave_status'; Variable_name Value @@ -67,24 +71,20 @@ show status like 'Rpl_semi_sync_master_clients'; Variable_name Value Rpl_semi_sync_master_clients 2 #-- Prepare servers to simulate delay or error -connection server_1; -SET @@GLOBAL.debug_dbug= ""; connection server_2; SET @@GLOBAL.debug_dbug= "+d,simulate_delay_semisync_slave_reply"; connection server_3; SET @@GLOBAL.debug_dbug= "+d,simulate_delay_semisync_slave_reply"; #-- #-- Test begins +connection server_1_con2; +#-- Give enough time after timeout/ack received to query yes_tx/no_tx +SET @@GLOBAL.debug_dbug= "+d,delay_shutdown_phase_2_after_semisync_wait"; connection server_1; #-- Begin semi-sync transaction INSERT INTO t1 VALUES (1); connection server_1_con2; #-- Wait until master recognizes a connection is awaiting semi-sync ACK -show status like 'Rpl_semi_sync_master_wait_sessions'; -Variable_name Value -Rpl_semi_sync_master_wait_sessions 1 -#-- Give enough time after timeout/ack received to query yes_tx/no_tx -SET @@GLOBAL.debug_dbug= "+d,delay_shutdown_phase_2_after_semisync_wait"; #-- Begin master shutdown SHUTDOWN WAIT FOR ALL SLAVES; connection server_1; @@ -111,22 +111,19 @@ count(*)=1 #-- Re-synchronize slaves with master and disable semi-sync #-- Stop slaves connection server_2; -SET @@GLOBAL.debug_dbug= ""; -SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0; -include/stop_slave.inc +include/stop_slave_io.inc +include/stop_slave_sql.inc +SET @@GLOBAL.debug_dbug= @sav_server_2_dbug; +SET @@GLOBAL.rpl_semi_sync_slave_enabled= @sav_enabled_server_2; connection server_3; -SET @@GLOBAL.debug_dbug= ""; -SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0; -include/stop_slave.inc +include/stop_slave_io.inc +include/stop_slave_sql.inc +SET @@GLOBAL.debug_dbug= @sav_server_3_dbug; +SET @@GLOBAL.rpl_semi_sync_slave_enabled= @sav_enabled_server_3; #-- Bring the master back up connection server_1_con2; connection default; connection server_1; -SET @@GLOBAL.debug_dbug= ""; -SET @@GLOBAL.rpl_semi_sync_master_enabled = 0; -show status like 'Rpl_semi_sync_master_status'; -Variable_name Value -Rpl_semi_sync_master_status OFF TRUNCATE TABLE t1; #-- Bring slaves back up connection server_2; @@ -157,15 +154,15 @@ connection server_1; #-- Enable semi-sync on slaves let slave_last= 3 connection server_2; -set global rpl_semi_sync_slave_enabled = 1; include/stop_slave.inc +set global rpl_semi_sync_slave_enabled = 1; include/start_slave.inc show status like 'Rpl_semi_sync_slave_status'; Variable_name Value Rpl_semi_sync_slave_status ON connection server_3; -set global rpl_semi_sync_slave_enabled = 1; include/stop_slave.inc +set global rpl_semi_sync_slave_enabled = 1; include/start_slave.inc show status like 'Rpl_semi_sync_slave_status'; Variable_name Value @@ -184,24 +181,20 @@ show status like 'Rpl_semi_sync_master_clients'; Variable_name Value Rpl_semi_sync_master_clients 2 #-- Prepare servers to simulate delay or error -connection server_1; -SET @@GLOBAL.debug_dbug= "+d,mysqld_delay_kill_threads_phase_1"; connection server_2; -SET @@GLOBAL.debug_dbug= "+d,corrupt_queue_event"; +SET @@GLOBAL.debug_dbug= "+d,corrupt_queue_event,delay_semisync_kill_connection_for_mdev_28141"; connection server_3; -SET @@GLOBAL.debug_dbug= "+d,corrupt_queue_event"; +SET @@GLOBAL.debug_dbug= "+d,corrupt_queue_event,delay_semisync_kill_connection_for_mdev_28141"; #-- #-- Test begins +connection server_1_con2; +#-- Give enough time after timeout/ack received to query yes_tx/no_tx +SET @@GLOBAL.debug_dbug= "+d,delay_shutdown_phase_2_after_semisync_wait"; connection server_1; #-- Begin semi-sync transaction INSERT INTO t1 VALUES (1); connection server_1_con2; #-- Wait until master recognizes a connection is awaiting semi-sync ACK -show status like 'Rpl_semi_sync_master_wait_sessions'; -Variable_name Value -Rpl_semi_sync_master_wait_sessions 1 -#-- Give enough time after timeout/ack received to query yes_tx/no_tx -SET @@GLOBAL.debug_dbug= "+d,delay_shutdown_phase_2_after_semisync_wait"; #-- Begin master shutdown SHUTDOWN WAIT FOR ALL SLAVES; connection server_1; @@ -226,24 +219,33 @@ count(*)=0 1 # #-- Re-synchronize slaves with master and disable semi-sync +#-- FIXME: workaround for MDEV-28141, preventing errored replicas from +# killing their semi-sync connections +connection server_2; +set debug_sync= "now wait_for at_semisync_kill_connection"; +set debug_sync= "now signal continue_semisync_kill_connection"; +# Wait for debug_sync signal to have been received before issuing RESET +set debug_sync= "reset"; +connection server_3; +set debug_sync= "now wait_for at_semisync_kill_connection"; +set debug_sync= "now signal continue_semisync_kill_connection"; +# Wait for debug_sync signal to have been received before issuing RESET +set debug_sync= "reset"; #-- Stop slaves connection server_2; -SET @@GLOBAL.debug_dbug= ""; -SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0; -include/stop_slave.inc +include/stop_slave_io.inc +include/stop_slave_sql.inc +SET @@GLOBAL.debug_dbug= @sav_server_2_dbug; +SET @@GLOBAL.rpl_semi_sync_slave_enabled= @sav_enabled_server_2; connection server_3; -SET @@GLOBAL.debug_dbug= ""; -SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0; -include/stop_slave.inc +include/stop_slave_io.inc +include/stop_slave_sql.inc +SET @@GLOBAL.debug_dbug= @sav_server_3_dbug; +SET @@GLOBAL.rpl_semi_sync_slave_enabled= @sav_enabled_server_3; #-- Bring the master back up connection server_1_con2; connection default; connection server_1; -SET @@GLOBAL.debug_dbug= ""; -SET @@GLOBAL.rpl_semi_sync_master_enabled = 0; -show status like 'Rpl_semi_sync_master_status'; -Variable_name Value -Rpl_semi_sync_master_status OFF TRUNCATE TABLE t1; #-- Bring slaves back up connection server_2; @@ -275,15 +277,15 @@ connection server_1; #-- Enable semi-sync on slaves let slave_last= 3 connection server_2; -set global rpl_semi_sync_slave_enabled = 1; include/stop_slave.inc +set global rpl_semi_sync_slave_enabled = 1; include/start_slave.inc show status like 'Rpl_semi_sync_slave_status'; Variable_name Value Rpl_semi_sync_slave_status ON connection server_3; -set global rpl_semi_sync_slave_enabled = 1; include/stop_slave.inc +set global rpl_semi_sync_slave_enabled = 1; include/start_slave.inc show status like 'Rpl_semi_sync_slave_status'; Variable_name Value @@ -302,24 +304,20 @@ show status like 'Rpl_semi_sync_master_clients'; Variable_name Value Rpl_semi_sync_master_clients 2 #-- Prepare servers to simulate delay or error -connection server_1; -SET @@GLOBAL.debug_dbug= "+d,mysqld_delay_kill_threads_phase_1"; connection server_2; -SET @@GLOBAL.debug_dbug= "+d,corrupt_queue_event"; +SET @@GLOBAL.debug_dbug= "+d,corrupt_queue_event,delay_semisync_kill_connection_for_mdev_28141"; connection server_3; SET @@GLOBAL.debug_dbug= "+d,simulate_delay_semisync_slave_reply"; #-- #-- Test begins +connection server_1_con2; +#-- Give enough time after timeout/ack received to query yes_tx/no_tx +SET @@GLOBAL.debug_dbug= "+d,delay_shutdown_phase_2_after_semisync_wait"; connection server_1; #-- Begin semi-sync transaction INSERT INTO t1 VALUES (1); connection server_1_con2; #-- Wait until master recognizes a connection is awaiting semi-sync ACK -show status like 'Rpl_semi_sync_master_wait_sessions'; -Variable_name Value -Rpl_semi_sync_master_wait_sessions 1 -#-- Give enough time after timeout/ack received to query yes_tx/no_tx -SET @@GLOBAL.debug_dbug= "+d,delay_shutdown_phase_2_after_semisync_wait"; #-- Begin master shutdown SHUTDOWN WAIT FOR ALL SLAVES; connection server_1; @@ -344,24 +342,28 @@ count(*)=1 1 # #-- Re-synchronize slaves with master and disable semi-sync +#-- FIXME: workaround for MDEV-28141, preventing errored replicas from +# killing their semi-sync connections +connection server_2; +set debug_sync= "now wait_for at_semisync_kill_connection"; +set debug_sync= "now signal continue_semisync_kill_connection"; +# Wait for debug_sync signal to have been received before issuing RESET +set debug_sync= "reset"; #-- Stop slaves connection server_2; -SET @@GLOBAL.debug_dbug= ""; -SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0; -include/stop_slave.inc +include/stop_slave_io.inc +include/stop_slave_sql.inc +SET @@GLOBAL.debug_dbug= @sav_server_2_dbug; +SET @@GLOBAL.rpl_semi_sync_slave_enabled= @sav_enabled_server_2; connection server_3; -SET @@GLOBAL.debug_dbug= ""; -SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0; -include/stop_slave.inc +include/stop_slave_io.inc +include/stop_slave_sql.inc +SET @@GLOBAL.debug_dbug= @sav_server_3_dbug; +SET @@GLOBAL.rpl_semi_sync_slave_enabled= @sav_enabled_server_3; #-- Bring the master back up connection server_1_con2; connection default; connection server_1; -SET @@GLOBAL.debug_dbug= ""; -SET @@GLOBAL.rpl_semi_sync_master_enabled = 0; -show status like 'Rpl_semi_sync_master_status'; -Variable_name Value -Rpl_semi_sync_master_status OFF TRUNCATE TABLE t1; #-- Bring slaves back up connection server_2; @@ -399,15 +401,15 @@ connection server_1; #-- Enable semi-sync on slaves let slave_last= 3 connection server_2; -set global rpl_semi_sync_slave_enabled = 1; include/stop_slave.inc +set global rpl_semi_sync_slave_enabled = 1; include/start_slave.inc show status like 'Rpl_semi_sync_slave_status'; Variable_name Value Rpl_semi_sync_slave_status ON connection server_3; -set global rpl_semi_sync_slave_enabled = 1; include/stop_slave.inc +set global rpl_semi_sync_slave_enabled = 1; include/start_slave.inc show status like 'Rpl_semi_sync_slave_status'; Variable_name Value @@ -426,24 +428,20 @@ show status like 'Rpl_semi_sync_master_clients'; Variable_name Value Rpl_semi_sync_master_clients 2 #-- Prepare servers to simulate delay or error -connection server_1; -SET @@GLOBAL.debug_dbug= "+d,mysqld_delay_kill_threads_phase_1"; connection server_2; -SET @@GLOBAL.debug_dbug= "+d,corrupt_queue_event,slave_delay_killing_semisync_connection"; +SET @@GLOBAL.debug_dbug= "+d,corrupt_queue_event,delay_semisync_kill_connection_for_mdev_28141"; connection server_3; SET @@GLOBAL.debug_dbug= "+d,simulate_delay_semisync_slave_reply"; #-- #-- Test begins +connection server_1_con2; +#-- Give enough time after timeout/ack received to query yes_tx/no_tx +SET @@GLOBAL.debug_dbug= "+d,delay_shutdown_phase_2_after_semisync_wait"; connection server_1; #-- Begin semi-sync transaction INSERT INTO t1 VALUES (1); connection server_1_con2; #-- Wait until master recognizes a connection is awaiting semi-sync ACK -show status like 'Rpl_semi_sync_master_wait_sessions'; -Variable_name Value -Rpl_semi_sync_master_wait_sessions 1 -#-- Give enough time after timeout/ack received to query yes_tx/no_tx -SET @@GLOBAL.debug_dbug= "+d,delay_shutdown_phase_2_after_semisync_wait"; #-- Begin master shutdown SHUTDOWN WAIT FOR ALL SLAVES; connection server_1; @@ -468,24 +466,28 @@ count(*)=1 1 # #-- Re-synchronize slaves with master and disable semi-sync +#-- FIXME: workaround for MDEV-28141, preventing errored replicas from +# killing their semi-sync connections +connection server_2; +set debug_sync= "now wait_for at_semisync_kill_connection"; +set debug_sync= "now signal continue_semisync_kill_connection"; +# Wait for debug_sync signal to have been received before issuing RESET +set debug_sync= "reset"; #-- Stop slaves connection server_2; -SET @@GLOBAL.debug_dbug= ""; -SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0; -include/stop_slave.inc +include/stop_slave_io.inc +include/stop_slave_sql.inc +SET @@GLOBAL.debug_dbug= @sav_server_2_dbug; +SET @@GLOBAL.rpl_semi_sync_slave_enabled= @sav_enabled_server_2; connection server_3; -SET @@GLOBAL.debug_dbug= ""; -SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0; -include/stop_slave.inc +include/stop_slave_io.inc +include/stop_slave_sql.inc +SET @@GLOBAL.debug_dbug= @sav_server_3_dbug; +SET @@GLOBAL.rpl_semi_sync_slave_enabled= @sav_enabled_server_3; #-- Bring the master back up connection server_1_con2; connection default; connection server_1; -SET @@GLOBAL.debug_dbug= ""; -SET @@GLOBAL.rpl_semi_sync_master_enabled = 0; -show status like 'Rpl_semi_sync_master_status'; -Variable_name Value -Rpl_semi_sync_master_status OFF TRUNCATE TABLE t1; #-- Bring slaves back up connection server_2; @@ -509,9 +511,13 @@ COUNT(*)=0 ############################# connection server_2; include/stop_slave.inc +SET @@GLOBAL.rpl_semi_sync_slave_enabled = @sav_enabled_server_2; +SET @@GLOBAL.debug_dbug= @sav_server_2_dbug; include/start_slave.inc connection server_3; include/stop_slave.inc +SET @@GLOBAL.rpl_semi_sync_slave_enabled = @sav_enabled_server_3; +SET @@GLOBAL.debug_dbug= @sav_server_3_dbug; include/start_slave.inc connection server_1; drop table t1; diff --git a/mysql-test/suite/rpl/t/rpl_change_master_demote.test b/mysql-test/suite/rpl/t/rpl_change_master_demote.test index 15b55014975..6304d3526d1 100644 --- a/mysql-test/suite/rpl/t/rpl_change_master_demote.test +++ b/mysql-test/suite/rpl/t/rpl_change_master_demote.test @@ -73,6 +73,9 @@ # non-boolean value. # # +# Additionally ensure MASTER_DEMOTE_TO_REPLICA aliases MASTER_DEMOTE_TO_SLAVE +# +# # References: # MDEV-19801: Change defaults for CHANGE MASTER TO so that GTID-based # replication is used by default if master supports it @@ -454,6 +457,37 @@ EOF --eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SLAVE_MYPORT, master_user='root', master_use_gtid=Slave_Pos, master_demote_to_slave=invalid +--echo # +--echo # MDEV-31768 +--echo # Ensure MASTER_DEMOTE_TO_REPLICA aliases MASTER_DEMOTE_TO_SLAVE +--echo # +--connection slave +RESET MASTER; +--source include/reset_slave.inc +CREATE TABLE t_mdev_31768 (a int); +--let $gtid_binlog_pos= `SELECT @@GLOBAL.gtid_binlog_pos` +CHANGE MASTER TO master_use_gtid=Replica_Pos, master_demote_to_replica=1; +--let $gtid_slave_pos= `SELECT @@GLOBAL.gtid_slave_pos` + +--echo # Validating alias MASTER_DEMOTE_TO_REPLICA provides intended behavior.. +if (`SELECT strcmp("$gtid_binlog_pos","$gtid_slave_pos") != 0`) +{ + --echo # ..failed + --echo # Binlog pos: $gtid_binlog_pos + --echo # Replica pos: $gtid_slave_pos + die MASTER_DEMOTE_TO_REPLICA does not alias MASTER_DEMOTE_TO_SLAVE correctly; +} +--echo # ..success + +DROP TABLE t_mdev_31768; +RESET MASTER; +--source include/reset_slave.inc + +--echo # Clear primary binlog state to match replica +--connection master +RESET MASTER; + + --echo # --echo # Cleanup --echo # diff --git a/mysql-test/suite/rpl/t/rpl_domain_id_filter_io_crash.test b/mysql-test/suite/rpl/t/rpl_domain_id_filter_io_crash.test index 95fac6c2edb..c7ef3a4eff9 100644 --- a/mysql-test/suite/rpl/t/rpl_domain_id_filter_io_crash.test +++ b/mysql-test/suite/rpl/t/rpl_domain_id_filter_io_crash.test @@ -9,6 +9,7 @@ CREATE TABLE t1(i INT) ENGINE=INNODB; INSERT INTO t1 VALUES(1); SELECT * FROM t1; sync_slave_with_master; +--source include/save_master_gtid.inc connection slave; @@ -28,7 +29,7 @@ let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Igno CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos; --source include/start_slave.inc -sync_with_master; +--source include/sync_with_master_gtid.inc let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); @@ -44,7 +45,7 @@ START TRANSACTION; INSERT INTO t1 VALUES(2); INSERT INTO t1 VALUES(3); COMMIT; -save_master_pos; +--source include/save_master_gtid.inc SELECT * FROM t1; connection slave; @@ -55,7 +56,7 @@ SET @@global.debug_dbug=@saved_dbug; START SLAVE io_thread; --source include/wait_for_slave_io_to_start.inc -sync_with_master; +--source include/sync_with_master_gtid.inc SELECT * FROM t1; --echo # Case 1 : Start slave with IGNORE_DOMAIN_IDS=(1), then restart @@ -70,7 +71,7 @@ let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Igno CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; --source include/start_slave.inc -sync_with_master; +--source include/sync_with_master_gtid.inc let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); @@ -86,7 +87,7 @@ INSERT INTO t1 VALUES(4); INSERT INTO t1 VALUES(5); COMMIT; -save_master_pos; +--source include/save_master_gtid.inc SELECT * FROM t1; connection slave; @@ -97,7 +98,7 @@ SET @@global.debug_dbug=@saved_dbug; START SLAVE io_thread; --source include/wait_for_slave_io_to_start.inc -sync_with_master; +--source include/sync_with_master_gtid.inc SELECT * FROM t1; --echo # Case 2 : Start slave with IGNORE_DOMAIN_IDS=(), then restart @@ -112,7 +113,7 @@ let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Igno CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos; --source include/start_slave.inc -sync_with_master; +--source include/sync_with_master_gtid.inc let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); @@ -140,7 +141,7 @@ INSERT INTO t1 VALUES(10); INSERT INTO t1 VALUES(11); COMMIT; -save_master_pos; +--source include/save_master_gtid.inc SELECT * FROM t1; connection slave; @@ -157,7 +158,7 @@ let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Igno CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; --source include/start_slave.inc -sync_with_master; +--source include/sync_with_master_gtid.inc let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); @@ -178,7 +179,7 @@ let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Igno CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; --source include/start_slave.inc -sync_with_master; +--source include/sync_with_master_gtid.inc let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); @@ -196,6 +197,15 @@ INSERT INTO t1 VALUES(12); INSERT INTO t1 VALUES(13); COMMIT; # IO thread gets killed here. +# MDEV-14357 +# As the prior transaction will be ignored on slave because its domain id is +# ignored, the replica's gtid_slave_pos will be updated to have seen it, +# despite its eventual failure to queue the whole transaction to the relay log. +# So for test consistency, we need to synchronize the SQL thread with this +# position; otherwise, when restarting the server after resetting +# IGNORE_DOMAIN_IDS, we will re-fetch this event and execute it. +--source include/save_master_gtid.inc + START TRANSACTION; INSERT INTO t1 VALUES(14); INSERT INTO t1 VALUES(15); @@ -207,7 +217,6 @@ INSERT INTO t1 VALUES(16); INSERT INTO t1 VALUES(17); COMMIT; -save_master_pos; SELECT * FROM t1; connection slave; @@ -217,6 +226,11 @@ SELECT * FROM t1; SET @@global.debug_dbug=@saved_dbug; +# MDEV-14357 +# Ensure the SQL thread is updated with the GTID of the ignored transaction +# so we don't fetch it and execute it after restarting without any ignored +# domain ids. +--source include/sync_with_master_gtid.inc --source include/stop_slave_sql.inc let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); @@ -224,8 +238,12 @@ let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Igno --echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos; + +--connection master +--source include/save_master_gtid.inc +--connection slave --source include/start_slave.inc -sync_with_master; +--source include/sync_with_master_gtid.inc let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); @@ -246,7 +264,7 @@ let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Igno CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; --source include/start_slave.inc -sync_with_master; +--source include/sync_with_master_gtid.inc let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); @@ -264,6 +282,11 @@ INSERT INTO t1 VALUES(18); INSERT INTO t1 VALUES(19); # IO thread gets killed here. COMMIT; +# MDEV-14357 +# Synchronize gtid_slave_pos with the ignored event. See prior comments about +# MDEV-14357 for details. +--source include/save_master_gtid.inc + START TRANSACTION; INSERT INTO t1 VALUES(20); INSERT INTO t1 VALUES(21); @@ -275,7 +298,6 @@ INSERT INTO t1 VALUES(22); INSERT INTO t1 VALUES(23); COMMIT; -save_master_pos; SELECT * FROM t1; connection slave; @@ -285,6 +307,10 @@ SELECT * FROM t1; SET @@global.debug_dbug=@saved_dbug; +# MDEV-14357 +# Synchronize gtid_slave_pos with the ignored event. See prior comments about +# MDEV-14357 for details. +--source include/sync_with_master_gtid.inc --source include/stop_slave_sql.inc let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); @@ -292,8 +318,12 @@ let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Igno --echo IGNORE_DOMAIN_IDS (BEFORE) : $ignore_domain_ids_before CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos; + +--connection master +--source include/save_master_gtid.inc +--connection slave --source include/start_slave.inc -sync_with_master; +--source include/sync_with_master_gtid.inc let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); @@ -314,7 +344,7 @@ let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Igno CHANGE MASTER TO IGNORE_DOMAIN_IDS=(), MASTER_USE_GTID=slave_pos; --source include/start_slave.inc -sync_with_master; +--source include/sync_with_master_gtid.inc let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); @@ -343,7 +373,7 @@ INSERT INTO t1 VALUES(28); INSERT INTO t1 VALUES(29); COMMIT; -save_master_pos; +--source include/save_master_gtid.inc SELECT * FROM t1; connection slave; @@ -361,7 +391,7 @@ let $ignore_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Igno CHANGE MASTER TO IGNORE_DOMAIN_IDS=(1), MASTER_USE_GTID=slave_pos; --source include/start_slave.inc -sync_with_master; +--source include/sync_with_master_gtid.inc let $do_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); let $ignore_domain_ids_after= query_get_value(SHOW SLAVE STATUS, Replicate_Ignore_Domain_Ids, 1); diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.inc b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.inc index 252541ae13b..a41ef2756d1 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.inc +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.inc @@ -3,7 +3,6 @@ # replicas before shutting down. # # Parameters: -# server_1_dbug (string) Debug setting for primary (server 1) # server_2_dbug (string) Debug setting to simulate delay or error on # the first replica (server 2) # server_3_dbug (string) Debug setting to simulate delay or error on @@ -32,8 +31,8 @@ while (`SELECT $i <= $slave_last`) --connection server_$i --sync_with_master - set global rpl_semi_sync_slave_enabled = 1; source include/stop_slave.inc; + set global rpl_semi_sync_slave_enabled = 1; source include/start_slave.inc; show status like 'Rpl_semi_sync_slave_status'; @@ -56,8 +55,6 @@ show status like 'Rpl_semi_sync_master_status'; show status like 'Rpl_semi_sync_master_clients'; --echo #-- Prepare servers to simulate delay or error ---connection server_1 ---eval SET @@GLOBAL.debug_dbug= $server_1_dbug --connection server_2 --eval SET @@GLOBAL.debug_dbug= $server_2_dbug --connection server_3 @@ -66,6 +63,14 @@ show status like 'Rpl_semi_sync_master_clients'; --echo #-- --echo #-- Test begins +--connection server_1_con2 +--echo #-- Give enough time after timeout/ack received to query yes_tx/no_tx +SET @@GLOBAL.debug_dbug= "+d,delay_shutdown_phase_2_after_semisync_wait"; + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF + --connection server_1 --echo #-- Begin semi-sync transaction --send INSERT INTO t1 VALUES (1) @@ -75,14 +80,6 @@ show status like 'Rpl_semi_sync_master_clients'; let $status_var= Rpl_semi_sync_master_wait_sessions; let $status_var_value= 1; source include/wait_for_status_var.inc; -show status like 'Rpl_semi_sync_master_wait_sessions'; - ---write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect -wait -EOF - ---echo #-- Give enough time after timeout/ack received to query yes_tx/no_tx -SET @@GLOBAL.debug_dbug= "+d,delay_shutdown_phase_2_after_semisync_wait"; --echo #-- Begin master shutdown --send SHUTDOWN WAIT FOR ALL SLAVES @@ -111,19 +108,72 @@ show status like 'Rpl_semi_sync_master_no_tx'; --echo # --echo #-- Re-synchronize slaves with master and disable semi-sync +if (`SELECT ($server_2_expect_row_count + $server_3_expect_row_count) < 2`) +{ +--echo #-- FIXME: workaround for MDEV-28141, preventing errored replicas from +--echo # killing their semi-sync connections +# I.e. we can't create a new kill connection to the primary if we know that the +# primary is shutting down for risk of Packets out of order error. So we wait +# to hit a debug_sync point before the creation of the new kill_connection, and +# don't progress until the primary has been shutdown, so no new connection can +# be formed. +# Note this is only needed in the error case (using corrupt_queue_event), as +# the running io_thread will otherwise automatically detect that the primary +# has shutdown before progressing to the cleanup of the io thread. +} + +if (!$server_2_expect_row_count) +{ + --connection server_2 + set debug_sync= "now wait_for at_semisync_kill_connection"; + set debug_sync= "now signal continue_semisync_kill_connection"; + --echo # Wait for debug_sync signal to have been received before issuing RESET + let $wait_condition= select count(*)=0 from information_schema.processlist where state like "debug sync point%"; + source include/wait_condition.inc; + set debug_sync= "reset"; +} +if (!$server_3_expect_row_count) +{ + --connection server_3 + set debug_sync= "now wait_for at_semisync_kill_connection"; + set debug_sync= "now signal continue_semisync_kill_connection"; + --echo # Wait for debug_sync signal to have been received before issuing RESET + let $wait_condition= select count(*)=0 from information_schema.processlist where state like "debug sync point%"; + source include/wait_condition.inc; + set debug_sync= "reset"; +} + --echo #-- Stop slaves --connection server_2 ---eval SET @@GLOBAL.debug_dbug= "$sav_server_2_dbug" ---eval SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0 ---let $rpl_only_running_threads= 1 -source include/stop_slave.inc; +# If server_2_expect_row_count is 0, we are simulating an error on the replica +# and the IO thread will end with errno 1595. +# Otherwise, we still expect error, because the master has shutdown at this +# point, and the IO thread may or may not have realized the shutdown, and +# started to try to automatically reconnect. This may result in the IO thread +# giving a 2003 error if the slave tries to reconnect to a shutdown master. +# Additionally disable warnings because the slave may have stopped in err +# automatically, and we don't want a sporadic "Slave is already stopped" +# warning. +--disable_warnings +--let $rpl_allow_error= 1 +--source include/stop_slave_io.inc +--enable_warnings +--let $rpl_allow_error= +--source include/stop_slave_sql.inc +SET @@GLOBAL.debug_dbug= @sav_server_2_dbug; +SET @@GLOBAL.rpl_semi_sync_slave_enabled= @sav_enabled_server_2; --connection server_3 ---eval SET @@GLOBAL.debug_dbug= "$sav_server_3_dbug" ---eval SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0 ---let $rpl_only_running_threads= 1 -source include/stop_slave.inc; +# Expect error for IO thread, see above comment for stopping server_2 +--disable_warnings +--let $rpl_allow_error= 1 +--source include/stop_slave_io.inc +--enable_warnings +--let $rpl_allow_error= +--source include/stop_slave_sql.inc +SET @@GLOBAL.debug_dbug= @sav_server_3_dbug; +SET @@GLOBAL.rpl_semi_sync_slave_enabled= @sav_enabled_server_3; --echo #-- Bring the master back up --connection server_1_con2 @@ -142,13 +192,6 @@ EOF --enable_reconnect --source include/wait_until_connected_again.inc ---eval SET @@GLOBAL.debug_dbug= "$sav_master_dbug" -let $status_var= Rpl_semi_sync_master_clients; -let $status_var_value= 0; -source include/wait_for_status_var.inc; ---eval SET @@GLOBAL.rpl_semi_sync_master_enabled = 0 -show status like 'Rpl_semi_sync_master_status'; - TRUNCATE TABLE t1; --save_master_pos diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.test b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.test index 6c088c571f2..fca6de4c209 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.test +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.test @@ -69,9 +69,8 @@ call mtr.add_suppression("Timeout waiting"); call mtr.add_suppression("did not exit"); call mtr.add_suppression("Got an error reading communication packets"); ---let $sav_master_timeout= `SELECT @@global.rpl_semi_sync_master_timeout` +--let $sav_master_timeout= `SELECT @@GLOBAL.rpl_semi_sync_master_timeout` --let $sav_enabled_master= `SELECT @@GLOBAL.rpl_semi_sync_master_enabled` ---let $sav_master_dbug= `SELECT @@GLOBAL.debug_dbug` --echo # Suppress slave errors related to the simulated error --connection server_2 @@ -79,16 +78,16 @@ call mtr.add_suppression("reply failed"); call mtr.add_suppression("Replication event checksum verification"); call mtr.add_suppression("Relay log write failure"); call mtr.add_suppression("Failed to kill the active semi-sync connection"); ---let $sav_enabled_server_2=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled` ---let $sav_server_2_dbug= `SELECT @@GLOBAL.debug_dbug` +set @sav_enabled_server_2= @@GLOBAL.rpl_semi_sync_slave_enabled; +set @sav_server_2_dbug= @@GLOBAL.debug_dbug; --connection server_3 call mtr.add_suppression("reply failed"); call mtr.add_suppression("Replication event checksum verification"); call mtr.add_suppression("Relay log write failure"); call mtr.add_suppression("Failed to kill the active semi-sync connection"); ---let $sav_enabled_server_3=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled` ---let $sav_server_3_dbug= `SELECT @@GLOBAL.debug_dbug` +set @sav_enabled_server_3= @@GLOBAL.rpl_semi_sync_slave_enabled; +set @sav_server_3_dbug= @@GLOBAL.debug_dbug; --connection server_1 CREATE TABLE t1 (a int); @@ -116,7 +115,6 @@ while (`SELECT $i <= $slave_last`) --echo # allowed timeout, the primary should delay killing the suspended thread --echo # until an ACK is received (Rpl_semi_sync_master_yes_tx should be 1). --echo # ---let server_1_dbug= "" --let server_2_dbug= "+d,simulate_delay_semisync_slave_reply" --let server_3_dbug= "+d,simulate_delay_semisync_slave_reply" --let semisync_timeout= 1600 @@ -129,9 +127,8 @@ while (`SELECT $i <= $slave_last`) --echo # the primary should delay killing the suspended thread until the --echo # timeout is reached (Rpl_semi_sync_master_no_tx should be 1). --echo # ---let server_1_dbug= "+d,mysqld_delay_kill_threads_phase_1" ---let server_2_dbug= "+d,corrupt_queue_event" ---let server_3_dbug= "+d,corrupt_queue_event" +--let server_2_dbug= "+d,corrupt_queue_event,delay_semisync_kill_connection_for_mdev_28141" +--let server_3_dbug= "+d,corrupt_queue_event,delay_semisync_kill_connection_for_mdev_28141" --let semisync_timeout= 500 --let server_2_expect_row_count= 0 --let server_3_expect_row_count= 0 @@ -143,8 +140,7 @@ while (`SELECT $i <= $slave_last`) --echo # primary should delay killing the suspended thread until it receives an --echo # ACK from the delayed slave (Rpl_semi_sync_master_yes_tx should be 1). --echo # ---let server_1_dbug= "+d,mysqld_delay_kill_threads_phase_1" ---let server_2_dbug= "+d,corrupt_queue_event" +--let server_2_dbug= "+d,corrupt_queue_event,delay_semisync_kill_connection_for_mdev_28141" --let server_3_dbug= "+d,simulate_delay_semisync_slave_reply" --let semisync_timeout= 1600 --let server_2_expect_row_count= 0 @@ -163,15 +159,7 @@ while (`SELECT $i <= $slave_last`) --echo # slave does not send a `QUIT` in this case (Rpl_semi_sync_master_yes_tx --echo # should be 1 because server_3 will send the ACK within a valid timeout). --echo # - -# mysqld_delay_kill_threads_phase1 ensures that server_2 will have enough time -# to start a new connection that has the intent to kill the active semi-sync -# connection ---let server_1_dbug= "+d,mysqld_delay_kill_threads_phase_1" - -# slave_delay_killing_semisync_connection ensures that the primary has force -# killed its current connection before it is able to issue `KILL` ---let server_2_dbug= "+d,corrupt_queue_event,slave_delay_killing_semisync_connection" +--let server_2_dbug= "+d,corrupt_queue_event,delay_semisync_kill_connection_for_mdev_28141" --let server_3_dbug= "+d,simulate_delay_semisync_slave_reply" --let semisync_timeout= 1600 --let server_2_expect_row_count= 0 @@ -184,32 +172,24 @@ while (`SELECT $i <= $slave_last`) --connection server_2 source include/stop_slave.inc; +SET @@GLOBAL.rpl_semi_sync_slave_enabled = @sav_enabled_server_2; +SET @@GLOBAL.debug_dbug= @sav_server_2_dbug; source include/start_slave.inc; ---disable_query_log ---eval SET @@GLOBAL.rpl_semi_sync_slave_enabled = $sav_enabled_server_2 ---eval SET @@GLOBAL.debug_dbug= "$sav_server_2_dbug" ---enable_query_log - --connection server_3 source include/stop_slave.inc; +SET @@GLOBAL.rpl_semi_sync_slave_enabled = @sav_enabled_server_3; +SET @@GLOBAL.debug_dbug= @sav_server_3_dbug; source include/start_slave.inc; ---disable_query_log ---eval SET @@GLOBAL.rpl_semi_sync_slave_enabled = $sav_enabled_server_3 ---eval SET @@GLOBAL.debug_dbug= "$sav_server_3_dbug" ---enable_query_log - - --connection server_1 let $status_var= Rpl_semi_sync_master_clients; let $status_var_value= 0; source include/wait_for_status_var.inc; --disable_query_log ---eval SET @@GLOBAL.rpl_semi_sync_master_timeout= $sav_master_timeout ---eval SET @@GLOBAL.rpl_semi_sync_master_enabled= $sav_enabled_master ---eval SET @@GLOBAL.debug_dbug= "$sav_master_dbug" +--eval SET @@GLOBAL.rpl_semi_sync_master_timeout= $sav_master_timeout; +--eval SET @@GLOBAL.rpl_semi_sync_master_enabled= $sav_enabled_master; --enable_query_log drop table t1; diff --git a/mysql-test/suite/sys_vars/r/innodb_fil_make_page_dirty_debug_basic.result b/mysql-test/suite/sys_vars/r/innodb_fil_make_page_dirty_debug_basic.result index abf2cdaf1c4..8bea17482c0 100644 --- a/mysql-test/suite/sys_vars/r/innodb_fil_make_page_dirty_debug_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_fil_make_page_dirty_debug_basic.result @@ -20,7 +20,4 @@ where name = 'test/t1' into @space_id; set global innodb_saved_page_number_debug = 0; set global innodb_fil_make_page_dirty_debug = @space_id; drop table t1; -# Must always be 0. -SELECT @@global.innodb_fil_make_page_dirty_debug; -@@global.innodb_fil_make_page_dirty_debug -0 +set global innodb_fil_make_page_dirty_debug = 0; diff --git a/mysql-test/suite/sys_vars/r/innodb_saved_page_number_debug_basic.result b/mysql-test/suite/sys_vars/r/innodb_saved_page_number_debug_basic.result index 20e2b78e640..1fc959f419d 100644 --- a/mysql-test/suite/sys_vars/r/innodb_saved_page_number_debug_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_saved_page_number_debug_basic.result @@ -21,6 +21,7 @@ set global innodb_saved_page_number_debug = 0; set global innodb_fil_make_page_dirty_debug = @space_id; drop table t1; set global innodb_saved_page_number_debug = 0; +set global innodb_fil_make_page_dirty_debug = 0; SELECT @@global.innodb_saved_page_number_debug; @@global.innodb_saved_page_number_debug 0 diff --git a/mysql-test/suite/sys_vars/t/innodb_fil_make_page_dirty_debug_basic.test b/mysql-test/suite/sys_vars/t/innodb_fil_make_page_dirty_debug_basic.test index 396d30c76c8..8bc7bd2dc4b 100644 --- a/mysql-test/suite/sys_vars/t/innodb_fil_make_page_dirty_debug_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_fil_make_page_dirty_debug_basic.test @@ -31,6 +31,4 @@ set global innodb_saved_page_number_debug = 0; set global innodb_fil_make_page_dirty_debug = @space_id; drop table t1; ---echo # Must always be 0. -SELECT @@global.innodb_fil_make_page_dirty_debug; - +set global innodb_fil_make_page_dirty_debug = 0; diff --git a/mysql-test/suite/sys_vars/t/innodb_saved_page_number_debug_basic.test b/mysql-test/suite/sys_vars/t/innodb_saved_page_number_debug_basic.test index d0996ae9a24..29b8451867a 100644 --- a/mysql-test/suite/sys_vars/t/innodb_saved_page_number_debug_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_saved_page_number_debug_basic.test @@ -32,6 +32,7 @@ set global innodb_fil_make_page_dirty_debug = @space_id; drop table t1; set global innodb_saved_page_number_debug = 0; +set global innodb_fil_make_page_dirty_debug = 0; SELECT @@global.innodb_saved_page_number_debug; diff --git a/mysql-test/suite/versioning/r/alter.result b/mysql-test/suite/versioning/r/alter.result index fed410f0157..bc7273c499d 100644 --- a/mysql-test/suite/versioning/r/alter.result +++ b/mysql-test/suite/versioning/r/alter.result @@ -844,8 +844,17 @@ Note 1060 Duplicate column name 'v' alter table `b` add column if not exists ( p bit ); drop table `b`; # -# End of 10.4 tests +# MDEV-30528 Assertion !mbmaxlen || ... failed +# in dtype_get_at_most_n_mbchars() # +CREATE TABLE t(f TEXT) WITH SYSTEM VERSIONING CHARACTER SET utf8 ENGINE=InnoDB; +INSERT INTO t VALUES ('foo'); +DELETE FROM t; +ALTER TABLE t ADD FULLTEXT (f); +affected rows: 1 +info: Records: 1 Duplicates: 0 Warnings: 0 +DROP TABLE t; +# End of 10.4 tests # # MDEV-21941 RENAME doesn't work for system time or period fields # @@ -869,6 +878,4 @@ t1 CREATE TABLE `t1` ( PERIOD FOR SYSTEM_TIME (`x`, `y`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci WITH SYSTEM VERSIONING drop table t1; -# # End of 10.5 tests -# diff --git a/mysql-test/suite/versioning/t/alter.test b/mysql-test/suite/versioning/t/alter.test index 44f52ddf747..85448d21346 100644 --- a/mysql-test/suite/versioning/t/alter.test +++ b/mysql-test/suite/versioning/t/alter.test @@ -743,9 +743,20 @@ alter table `b` add column if not exists ( p bit ); drop table `b`; --echo # ---echo # End of 10.4 tests +--echo # MDEV-30528 Assertion !mbmaxlen || ... failed +--echo # in dtype_get_at_most_n_mbchars() --echo # +CREATE TABLE t(f TEXT) WITH SYSTEM VERSIONING CHARACTER SET utf8 ENGINE=InnoDB; +INSERT INTO t VALUES ('foo'); +DELETE FROM t; +--enable_info +ALTER TABLE t ADD FULLTEXT (f); +--disable_info +DROP TABLE t; + +--echo # End of 10.4 tests + --echo # --echo # MDEV-21941 RENAME doesn't work for system time or period fields --echo # @@ -767,6 +778,4 @@ show create table t1; # cleanup drop table t1; ---echo # --echo # End of 10.5 tests ---echo # diff --git a/plugin/auth_pam/auth_pam_base.c b/plugin/auth_pam/auth_pam_base.c index 1e8f4a08def..153712df140 100644 --- a/plugin/auth_pam/auth_pam_base.c +++ b/plugin/auth_pam/auth_pam_base.c @@ -99,7 +99,7 @@ static int conv(int n, const struct pam_message **msg, freeing it is the responsibility of the caller */ if (*resp == 0) { - *resp = calloc(sizeof(struct pam_response), n); + *resp = calloc(n, sizeof(struct pam_response)); if (*resp == 0) return PAM_BUF_ERR; } 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/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index 2b05326e500..53172da7b96 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -803,7 +803,8 @@ recv_joiner() if [ $tmt -gt 0 ]; then if [ -n "$(commandex timeout)" ]; then local koption=0 - if [ "$OS" = 'FreeBSD' ]; then + if [ "$OS" = 'FreeBSD' -o "$OS" = 'NetBSD' -o "$OS" = 'OpenBSD' -o \ + "$OS" = 'DragonFly' ]; then if timeout 2>&1 | grep -qw -F -- '-k'; then koption=1 fi diff --git a/sql/field.cc b/sql/field.cc index 76b7ff61681..33aa7c60821 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1502,6 +1502,9 @@ bool Field::sp_prepare_and_store_item(THD *thd, Item **value) if (!(expr_item= thd->sp_fix_func_item_for_assignment(this, value))) goto error; + if (expr_item->check_is_evaluable_expression_or_error()) + goto error; + /* Save the value in the field. Convert the value if needed. */ expr_item->save_in_field(this, 0); @@ -11481,6 +11484,30 @@ bool Field::validate_value_in_record_with_warn(THD *thd, const uchar *record) } +/** + Find which reaction should be for IGNORE value. +*/ + +ignore_value_reaction find_ignore_reaction(THD *thd) +{ + enum_sql_command com= thd->lex->sql_command; + + // All insert-like commands + if (com == SQLCOM_INSERT || com == SQLCOM_REPLACE || + com == SQLCOM_INSERT_SELECT || com == SQLCOM_REPLACE_SELECT || + com == SQLCOM_LOAD) + { + return IGNORE_MEANS_DEFAULT; + } + // Update commands + if (com == SQLCOM_UPDATE || com == SQLCOM_UPDATE_MULTI) + { + return IGNORE_MEANS_FIELD_VALUE; + } + return IGNORE_MEANS_ERROR; +} + + bool Field::save_in_field_default_value(bool view_error_processing) { THD *thd= table->in_use; diff --git a/sql/field.h b/sql/field.h index 8563375f3e3..d57a471a694 100644 --- a/sql/field.h +++ b/sql/field.h @@ -63,6 +63,15 @@ enum enum_check_fields CHECK_FIELD_ERROR_FOR_NULL, }; +enum ignore_value_reaction +{ + IGNORE_MEANS_ERROR, + IGNORE_MEANS_DEFAULT, + IGNORE_MEANS_FIELD_VALUE +}; + +ignore_value_reaction find_ignore_reaction(THD *thd); + enum enum_conv_type { diff --git a/sql/handler.cc b/sql/handler.cc index 0270e206203..7482258ed30 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1877,12 +1877,17 @@ int ha_commit_trans(THD *thd, bool all) // Issue a message to the client and roll back the transaction. if (trans->no_2pc && rw_ha_count > 1) { - my_message(ER_ERROR_DURING_COMMIT, "Transactional commit not supported " - "by involved engine(s)", MYF(0)); - error= 1; + // REPLACE|INSERT INTO ... SELECT uses TOI for MyISAM|Aria + if (WSREP(thd) && thd->wsrep_cs().mode() != wsrep::client_state::m_toi) + { + my_message(ER_ERROR_DURING_COMMIT, "Transactional commit not supported " + "by involved engine(s)", MYF(0)); + error= 1; + } } - else - error= wsrep_before_commit(thd, all); + + if (!error) + error= wsrep_before_commit(thd, all); } if (error) { @@ -2255,8 +2260,12 @@ int ha_rollback_trans(THD *thd, bool all) } #ifdef WITH_WSREP - (void) wsrep_before_rollback(thd, all); + // REPLACE|INSERT INTO ... SELECT uses TOI in consistency check + if (thd->wsrep_consistency_check != CONSISTENCY_CHECK_RUNNING) + if (thd->wsrep_cs().mode() != wsrep::client_state::m_toi) + (void) wsrep_before_rollback(thd, all); #endif /* WITH_WSREP */ + if (ha_info) { /* Close all cursors that can not survive ROLLBACK */ @@ -2293,7 +2302,11 @@ int ha_rollback_trans(THD *thd, bool all) thd->thread_id, all?"TRUE":"FALSE", wsrep_thd_query(thd), thd->get_stmt_da()->message(), is_real_trans); } - (void) wsrep_after_rollback(thd, all); + + // REPLACE|INSERT INTO ... SELECT uses TOI in consistency check + if (thd->wsrep_consistency_check != CONSISTENCY_CHECK_RUNNING) + if (thd->wsrep_cs().mode() != wsrep::client_state::m_toi) + (void) wsrep_after_rollback(thd, all); #endif /* WITH_WSREP */ if (all || !thd->in_active_multi_stmt_transaction()) @@ -5186,7 +5199,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); } @@ -5235,7 +5248,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; } @@ -6169,7 +6182,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 b0777347cf3..44a38cf7507 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -2680,6 +2680,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/item.cc b/sql/item.cc index 954d33bbdd0..b6041effe4a 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4101,7 +4101,9 @@ Item_param::Item_param(THD *thd, const LEX_CSTRING *name_arg, as an actual parameter. See Item_param::set_from_item(). */ m_is_settable_routine_parameter(true), - m_clones(thd->mem_root) + m_clones(thd->mem_root), + m_associated_field(nullptr), + m_default_field(nullptr) { name= *name_arg; /* @@ -4508,10 +4510,29 @@ int Item_param::save_in_field(Field *field, bool no_conversions) case NULL_VALUE: return set_field_to_null_with_conversions(field, no_conversions); case DEFAULT_VALUE: + if (m_associated_field) + return assign_default(field); return field->save_in_field_default_value(field->table->pos_in_table_list-> top_table() != field->table->pos_in_table_list); case IGNORE_VALUE: + if (m_associated_field) + { + switch (find_ignore_reaction(field->table->in_use)) + { + case IGNORE_MEANS_DEFAULT: + DBUG_ASSERT(0); // impossible now, but fully working code if needed + return assign_default(field); + case IGNORE_MEANS_FIELD_VALUE: + m_associated_field->save_val(field); + return false; + default: + ; // fall through to error + } + DBUG_ASSERT(0); //impossible + my_error(ER_INVALID_DEFAULT_PARAM, MYF(0)); + return true; + } return field->save_in_field_ignore_value(field->table->pos_in_table_list-> top_table() != field->table->pos_in_table_list); @@ -5095,6 +5116,82 @@ bool Item_param::append_for_log(THD *thd, String *str) } +/** + Allocate a memory and create on it a copy of Field object. + + @param thd thread handler + @param field_arg an instance of Field the new Field object be based on + + @return a new created Field object on success, nullptr on error. +*/ + +static Field *make_default_field(THD *thd, Field *field_arg) +{ + Field *def_field; + + if (!(def_field= (Field*) thd->alloc(field_arg->size_of()))) + return nullptr; + + memcpy((void *)def_field, (void *)field_arg, field_arg->size_of()); + def_field->reset_fields(); + // If non-constant default value expression or a blob + if (def_field->default_value && + (def_field->default_value->flags || (def_field->flags & BLOB_FLAG))) + { + uchar *newptr= (uchar*) thd->alloc(1+def_field->pack_length()); + if (!newptr) + return nullptr; + + if (should_mark_column(thd->column_usage)) + def_field->default_value->expr->update_used_tables(); + def_field->move_field(newptr + 1, def_field->maybe_null() ? newptr : 0, 1); + } + else + def_field->move_field_offset((my_ptrdiff_t) + (def_field->table->s->default_values - + def_field->table->record[0])); + return def_field; +} + + +/** + Assign a default value of a table column to the positional parameter that + is performed on execution of a prepared statement with the clause + 'USING DEFAULT' + + @param field a field that should be assigned an actual value of positional + parameter passed via the clause 'USING DEFAULT' + + @return false on success, true on failure +*/ + +bool Item_param::assign_default(Field *field) +{ + DBUG_ASSERT(m_associated_field); + + if (m_associated_field->field->flags & NO_DEFAULT_VALUE_FLAG) + { + my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), + m_associated_field->field->field_name.str); + return true; + } + + if (!m_default_field) + { + m_default_field= make_default_field(field->table->in_use, + m_associated_field->field); + + if (!m_default_field) + return true; + } + + if (m_default_field->default_value) + m_default_field->set_default(); + + return field_conv(field, m_default_field); +} + + /**************************************************************************** Item_copy_string ****************************************************************************/ @@ -9612,69 +9709,10 @@ bool Item_default_value::update_func_default_processor(void *) bool Item_default_value::fix_fields(THD *thd, Item **items) { - Item *real_arg; - Item_field *field_arg; - Field *def_field; DBUG_ASSERT(fixed() == 0); DBUG_ASSERT(arg); - /* - DEFAULT() do not need table field so should not ask handler to bring - field value (mark column for read) - */ - enum_column_usage save_column_usage= thd->column_usage; - /* - Fields which has defult value could be read, so it is better hide system - invisible columns. - */ - thd->column_usage= COLUMNS_WRITE; - if (arg->fix_fields_if_needed(thd, &arg)) - { - thd->column_usage= save_column_usage; - goto error; - } - thd->column_usage= save_column_usage; - - real_arg= arg->real_item(); - if (real_arg->type() != FIELD_ITEM) - { - my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg->name.str); - goto error; - } - - field_arg= (Item_field *)real_arg; - if ((field_arg->field->flags & NO_DEFAULT_VALUE_FLAG)) - { - my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), - field_arg->field->field_name.str); - goto error; - } - if (!(def_field= (Field*) thd->alloc(field_arg->field->size_of()))) - goto error; - memcpy((void *)def_field, (void *)field_arg->field, - field_arg->field->size_of()); - def_field->reset_fields(); - // If non-constant default value expression or a blob - if (def_field->default_value && - (def_field->default_value->flags || (def_field->flags & BLOB_FLAG))) - { - uchar *newptr= (uchar*) thd->alloc(1+def_field->pack_length()); - if (!newptr) - goto error; - if (should_mark_column(thd->column_usage)) - def_field->default_value->expr->update_used_tables(); - def_field->move_field(newptr+1, def_field->maybe_null() ? newptr : 0, 1); - } - else - def_field->move_field_offset((my_ptrdiff_t) - (def_field->table->s->default_values - - def_field->table->record[0])); - set_field(def_field); - return FALSE; - -error: - context->process_error(thd); - return TRUE; + return tie_field(thd); } void Item_default_value::cleanup() @@ -9863,6 +9901,75 @@ Item *Item_default_value::transform(THD *thd, Item_transformer transformer, } +bool Item_default_value::associate_with_target_field(THD *thd, + Item_field *field) +{ + m_associated= true; + arg= field; + return tie_field(thd); +} + + +/** + Call fix_fields for an item representing the default value, create + an instance of Field for representing the default value and assign it + to the Item_field::field. + + @param thd thread handler + + @return false on success, true on error +*/ + +bool Item_default_value::tie_field(THD *thd) +{ + Item *real_arg; + Item_field *field_arg; + Field *def_field; + + /* + DEFAULT() do not need table field so should not ask handler to bring + field value (mark column for read) + */ + enum_column_usage save_column_usage= thd->column_usage; + /* + Fields which has defult value could be read, so it is better hide system + invisible columns. + */ + thd->column_usage= COLUMNS_WRITE; + if (arg->fix_fields_if_needed(thd, &arg)) + { + thd->column_usage= save_column_usage; + goto error; + } + thd->column_usage= save_column_usage; + + real_arg= arg->real_item(); + if (real_arg->type() != FIELD_ITEM) + { + my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg->name.str); + goto error; + } + + field_arg= (Item_field *)real_arg; + if ((field_arg->field->flags & NO_DEFAULT_VALUE_FLAG)) + { + my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), + field_arg->field->field_name.str); + goto error; + } + def_field= make_default_field(thd, field_arg->field); + if (!def_field) + goto error; + + set_field(def_field); + return false; + +error: + context->process_error(thd); + return true; + +} + bool Item_insert_value::eq(const Item *item, bool binary_cmp) const { return item->type() == INSERT_VALUE_ITEM && diff --git a/sql/item.h b/sql/item.h index 9b4ac86e2a8..e7c8569694d 100644 --- a/sql/item.h +++ b/sql/item.h @@ -946,7 +946,7 @@ protected: const Tmp_field_param *param, bool is_explicit_null); - void raise_error_not_evaluable(); + virtual void raise_error_not_evaluable(); void push_note_converted_to_negative_complement(THD *thd); void push_note_converted_to_positive_complement(THD *thd); @@ -2735,6 +2735,18 @@ public: Checks if this item consists in the left part of arg IN subquery predicate */ bool pushable_equality_checker_for_subquery(uchar *arg); + + /** + This method is to set relationship between a positional parameter + represented by the '?' and an actual argument value passed to the + call of PS/SP by the USING clause. The method is overridden in classes + Item_param and Item_default_value. + */ + virtual bool associate_with_target_field(THD *, Item_field *) + { + DBUG_ASSERT(fixed()); + return false; + } }; MEM_ROOT *get_thd_memroot(THD *thd); @@ -4341,6 +4353,10 @@ public: void sync_clones(); bool register_clone(Item_param *i) { return m_clones.push_back(i); } + void raise_error_not_evaluable() override + { + invalid_default_param(); + } private: void invalid_default_param() const; bool set_value(THD *thd, sp_rcontext *ctx, Item **it) override; @@ -4351,6 +4367,17 @@ public: Item_param *get_item_param() override { return this; } void make_send_field(THD *thd, Send_field *field) override; + /** + See comments on @see Item::associate_with_target_field for method + description + */ + bool associate_with_target_field(THD *, Item_field *field) override + { + m_associated_field= field; + return false; + } + bool assign_default(Field *field); + private: Send_field *m_out_param_info; bool m_is_settable_routine_parameter; @@ -4360,6 +4387,8 @@ private: synchronize the actual value of the parameter with the values of the clones. */ Mem_root_array m_clones; + Item_field *m_associated_field; + Field *m_default_field; }; @@ -6694,6 +6723,8 @@ public: class Item_default_value : public Item_field { bool vcol_assignment_ok; + bool m_associated= false; + void calculate(); public: Item *arg= nullptr; @@ -6762,6 +6793,15 @@ public: override; Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) override; + + /** + See comments on @see Item::associate_with_target_field for method + description + */ + bool associate_with_target_field(THD *thd, Item_field *field) override; + +private: + bool tie_field(THD *thd); }; diff --git a/sql/item_func.cc b/sql/item_func.cc index dd056ac4d68..462055e806f 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3540,6 +3540,7 @@ udf_handler::fix_fields(THD *thd, Item_func_or_sum *func, initid.const_item=func->const_item_cache; initid.decimals=func->decimals; initid.ptr=0; + not_original=0; for (uint i1= 0 ; i1 < arg_count ; i1++) buffers[i1].set_thread_specific(); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 89dc2083270..37999967c9b 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1499,6 +1499,7 @@ String *Item_func_sformat::val_str(String *res) bool Item_func_random_bytes::fix_length_and_dec(THD *thd) { + set_maybe_null(); used_tables_cache|= RAND_TABLE_BIT; if (args[0]->can_eval_in_optimize()) { diff --git a/sql/item_sum.h b/sql/item_sum.h index 7308734070d..2dad0bc3582 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -599,6 +599,17 @@ public: bool is_window_func_sum_expr() { return window_func_sum_expr_flag; } virtual void setup_caches(THD *thd) {}; virtual void set_partition_row_count(ulonglong count) { DBUG_ASSERT(0); } + + /* + While most Item_sum descendants employ standard aggregators configured + through Item_sum::set_aggregator() call, there are exceptions like + Item_func_group_concat, which implements its own custom aggregators for + deduplication values. + This function distinguishes between the use of standard and custom + aggregators by the object + */ + virtual bool uses_non_standard_aggregator_for_distinct() const + { return false; } }; @@ -2015,6 +2026,9 @@ protected: { return f->val_str(tmp, key + offset); } virtual void cut_max_length(String *result, uint old_length, uint max_length) const; + bool uses_non_standard_aggregator_for_distinct() const override + { return distinct; } + public: // Methods used by ColumnStore bool get_distinct() const { return distinct; } diff --git a/sql/lex.h b/sql/lex.h index b1f5718dfb3..ad37c39bca5 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -385,6 +385,7 @@ SYMBOL symbols[] = { { "MASTER_SSL_VERIFY_SERVER_CERT", SYM(MASTER_SSL_VERIFY_SERVER_CERT_SYM)}, { "MASTER_USER", SYM(MASTER_USER_SYM)}, { "MASTER_USE_GTID", SYM(MASTER_USE_GTID_SYM)}, + { "MASTER_DEMOTE_TO_REPLICA", SYM(MASTER_DEMOTE_TO_SLAVE_SYM)}, { "MASTER_DEMOTE_TO_SLAVE", SYM(MASTER_DEMOTE_TO_SLAVE_SYM)}, { "MASTER_HEARTBEAT_PERIOD", SYM(MASTER_HEARTBEAT_PERIOD_SYM)}, { "MATCH", SYM(MATCH)}, diff --git a/sql/mdl.cc b/sql/mdl.cc index 32374415a2e..13a97b8e58b 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -1195,15 +1195,8 @@ MDL_wait::timed_wait(MDL_context_owner *owner, struct timespec *abs_timeout, { #ifdef WITH_WSREP # ifdef ENABLED_DEBUG_SYNC - // Allow tests to block the applier thread using the DBUG facilities - DBUG_EXECUTE_IF("sync.wsrep_before_mdl_wait", - { - const char act[]= - "now " - "wait_for signal.wsrep_before_mdl_wait"; - DBUG_ASSERT(!debug_sync_set_action((owner->get_thd()), - STRING_WITH_LEN(act))); - };); + // Allow tests to block thread before MDL-wait + DEBUG_SYNC(owner->get_thd(), "wsrep_before_mdl_wait"); # endif if (WSREP_ON && wsrep_thd_is_BF(owner->get_thd(), false)) { diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 83d230b7ffd..a5641668503 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1773,7 +1773,6 @@ static void close_connections(void) This will give the threads some time to gracefully abort their statements and inform their clients that the server is about to die. */ - DBUG_EXECUTE_IF("mysqld_delay_kill_threads_phase_1", my_sleep(200000);); int n_threads_awaiting_ack= 0; server_threads.iterate(kill_thread_phase_1, &n_threads_awaiting_ack); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index cb018bac2e9..66a6e565f0c 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3200,6 +3200,53 @@ SQL_SELECT::test_quick_select(THD *thd, ****************************************************************************/ +/* + @brief + Create a bitmap of columns for which to perform Range Analysis for EITS + condition selectivity estimates. + + @detail + Walk through the bitmap of fields used in the query, and + - pick columns for which EITS data is usable (see is_eits_usable() call) + - do not produce more than MAX_KEY columns. Range Analyzer cannot handle + more than that. If there are more than MAX_KEY eligible columns, + this function should be called multiple times to produce multiple + bitmaps. + + @param used_fields Columns used by the query + @param col_no Start from this column + @param out OUT Filled column bitmap + + @return + (uint)-1 If there are no more columns for range analysis. + Other Index of the last considered column. Pass this to next call to + this function +*/ + +uint get_columns_for_pseudo_indexes(const TABLE *table, + const MY_BITMAP *used_fields, int col_no, + MY_BITMAP *out) +{ + bitmap_clear_all(out); + int n_bits= 0; + + for (; table->field[col_no]; col_no++) + { + if (bitmap_is_set(used_fields, col_no) && + is_eits_usable(table->field[col_no])) + { + bitmap_set_bit(out, col_no); + if (++n_bits == MAX_KEY) + { + col_no++; + break; + } + } + } + return n_bits? col_no: (uint)-1; +} + + /* Build descriptors of pseudo-indexes over columns to perform range analysis @@ -3225,22 +3272,11 @@ bool create_key_parts_for_pseudo_indexes(RANGE_OPT_PARAM *param, { Field **field_ptr; TABLE *table= param->table; - uint parts= 0; - - for (field_ptr= table->field; *field_ptr; field_ptr++) - { - Field *field= *field_ptr; - if (bitmap_is_set(used_fields, field->field_index) && - is_eits_usable(field)) - parts++; - } + uint parts= bitmap_bits_set(used_fields); KEY_PART *key_part; uint keys= 0; - if (!parts) - return TRUE; - if (!(key_part= (KEY_PART *) alloc_root(param->mem_root, sizeof(KEY_PART) * parts))) return TRUE; @@ -3252,9 +3288,6 @@ bool create_key_parts_for_pseudo_indexes(RANGE_OPT_PARAM *param, Field *field= *field_ptr; if (bitmap_is_set(used_fields, field->field_index)) { - if (!is_eits_usable(field)) - continue; - uint16 store_length; uint16 max_key_part_length= (uint16) table->file->max_key_part_length(); key_part->key= keys; @@ -3656,8 +3689,6 @@ end_of_range_loop: PARAM param; MEM_ROOT alloc; SEL_TREE *tree; - double rows; - init_sql_alloc(key_memory_quick_range_select_root, &alloc, thd->variables.range_alloc_block_size, 0, MYF(MY_THREAD_SPECIFIC)); @@ -3668,68 +3699,93 @@ end_of_range_loop: param.table= table; param.remove_false_where_parts= true; - if (create_key_parts_for_pseudo_indexes(¶m, used_fields)) - goto free_alloc; - param.prev_tables= param.read_tables= 0; param.current_table= table->map; param.using_real_indexes= FALSE; - param.real_keynr[0]= 0; + MEM_UNDEFINED(¶m.real_keynr, sizeof(param.real_keynr)); + param.alloced_sel_args= 0; param.max_key_parts= 0; - thd->no_errors=1; - - if (!(tree= cond[0]->get_mm_tree(¶m, cond))) - goto free_alloc; - + thd->no_errors=1; table->reginfo.impossible_range= 0; - if (tree->type == SEL_TREE::IMPOSSIBLE) - { - rows= 0; - table->reginfo.impossible_range= 1; - goto free_alloc; - } - else if (tree->type == SEL_TREE::ALWAYS) - { - rows= table_records; - goto free_alloc; - } - else if (tree->type == SEL_TREE::MAYBE) - { - rows= table_records; - goto free_alloc; - } - for (uint idx= 0; idx < param.keys; idx++) + uint used_fields_buff_size= bitmap_buffer_size(table->s->fields); + uint32 *used_fields_buff= (uint32*)thd->alloc(used_fields_buff_size); + MY_BITMAP cols_for_indexes; + (void) my_bitmap_init(&cols_for_indexes, used_fields_buff, table->s->fields); + bitmap_clear_all(&cols_for_indexes); + + uint column_no= 0; // Start looping from the first column. + /* + Try getting selectivity estimates for every field that is used in the + query and has EITS statistics. We do this: + + for every usable field col + create a pseudo INDEX(col); + Run the range analyzer (get_mm_tree) for these pseudo-indexes; + Look at produced ranges and get their selectivity estimates; + + Note that the range analyzer can process at most MAX_KEY indexes. If + the table has >MAX_KEY eligible columns, we will do several range + analyzer runs. + */ + + while (1) { - SEL_ARG *key= tree->keys[idx]; - if (key) // Quick range found for key + column_no= get_columns_for_pseudo_indexes(table, used_fields, column_no, + &cols_for_indexes); + if (column_no == (uint)-1) + break; /* Couldn't create any pseudo-indexes. This means we're done */ + + if (create_key_parts_for_pseudo_indexes(¶m, &cols_for_indexes)) + goto free_alloc; + + tree= cond[0]->get_mm_tree(¶m, cond); + + if (!tree || + tree->type == SEL_TREE::ALWAYS || + tree->type == SEL_TREE::MAYBE) { - Json_writer_object selectivity_for_column(thd); - selectivity_for_column.add("column_name", key->field->field_name); - if (key->type == SEL_ARG::IMPOSSIBLE) + /* Couldn't infer anything. But there could be more fields, so continue */ + continue; + } + + if (tree->type == SEL_TREE::IMPOSSIBLE) + { + table->reginfo.impossible_range= 1; + goto free_alloc; + } + + for (uint idx= 0; idx < param.keys; idx++) + { + SEL_ARG *key= tree->keys[idx]; + if (key) { - rows= 0; - table->reginfo.impossible_range= 1; - if (unlikely(selectivity_for_column.trace_started())) - selectivity_for_column. - add("selectivity_from_histogram", rows). - add("cause", "impossible range"); - goto free_alloc; - } - else - { - enum_check_fields save_count_cuted_fields= thd->count_cuted_fields; - thd->count_cuted_fields= CHECK_FIELD_IGNORE; - rows= records_in_column_ranges(¶m, idx, key); - thd->count_cuted_fields= save_count_cuted_fields; - if (rows != DBL_MAX) + Json_writer_object selectivity_for_column(thd); + selectivity_for_column.add("column_name", key->field->field_name); + if (key->type == SEL_ARG::IMPOSSIBLE) { - key->field->cond_selectivity= rows/table_records; DBUG_ASSERT(key->field->cond_selectivity <= 1.0); - selectivity_for_column.add("selectivity_from_histogram", - key->field->cond_selectivity); + table->reginfo.impossible_range= 1; + if (unlikely(selectivity_for_column.trace_started())) + selectivity_for_column. + add("selectivity_from_histogram", 0). + add("cause", "impossible range"); + goto free_alloc; + } + else + { + enum_check_fields save_count_cuted_fields= thd->count_cuted_fields; + thd->count_cuted_fields= CHECK_FIELD_IGNORE; + double rows= records_in_column_ranges(¶m, idx, key); + thd->count_cuted_fields= save_count_cuted_fields; + if (rows != DBL_MAX) + { + key->field->cond_selectivity= rows/table_records; + selectivity_for_column.add("selectivity_from_histogram", + key->field->cond_selectivity); + } } } } diff --git a/sql/semisync_master.cc b/sql/semisync_master.cc index 9f30a8206a4..8cc721e5737 100644 --- a/sql/semisync_master.cc +++ b/sql/semisync_master.cc @@ -844,7 +844,7 @@ int Repl_semi_sync_master::commit_trx(const char* trx_wait_binlog_name, int wait_result; PSI_stage_info old_stage; THD *thd= current_thd; - bool aborted= 0; + bool aborted __attribute__((unused)) = 0; set_timespec(start_ts, 0); DEBUG_SYNC(thd, "rpl_semisync_master_commit_trx_before_lock"); diff --git a/sql/semisync_master_ack_receiver.h b/sql/semisync_master_ack_receiver.h index eacb4b200c0..817df513069 100644 --- a/sql/semisync_master_ack_receiver.h +++ b/sql/semisync_master_ack_receiver.h @@ -186,7 +186,7 @@ public: char buff[100]; /* Clear the signal message */ #ifndef _WIN32 - read(local_read_signal, buff, sizeof(buff)); + (void) !read(local_read_signal, buff, sizeof(buff)); #else recv(local_read_signal, buff, sizeof(buff), 0); #endif /* _WIN32 */ diff --git a/sql/semisync_slave.cc b/sql/semisync_slave.cc index 4314b116287..3bd6d135087 100644 --- a/sql/semisync_slave.cc +++ b/sql/semisync_slave.cc @@ -17,6 +17,7 @@ #include #include "semisync_slave.h" +#include "debug_sync.h" Repl_semi_sync_slave repl_semisync_slave; @@ -128,7 +129,21 @@ void Repl_semi_sync_slave::slave_start(Master_info *mi) void Repl_semi_sync_slave::slave_stop(Master_info *mi) { if (get_slave_enabled()) + { +#ifdef ENABLED_DEBUG_SYNC + /* + TODO: Remove after MDEV-28141 + */ + DBUG_EXECUTE_IF("delay_semisync_kill_connection_for_mdev_28141", { + const char act[]= "now " + "signal at_semisync_kill_connection " + "wait_for continue_semisync_kill_connection"; + DBUG_ASSERT(debug_sync_service); + DBUG_ASSERT(!debug_sync_set_action(mi->io_thd, STRING_WITH_LEN(act))); + };); +#endif kill_connection(mi->mysql); + } set_slave_enabled(0); } @@ -167,8 +182,6 @@ void Repl_semi_sync_slave::kill_connection(MYSQL *mysql) goto failed_graceful_kill; } - DBUG_EXECUTE_IF("slave_delay_killing_semisync_connection", my_sleep(400000);); - kill_buffer_length= my_snprintf(kill_buffer, 30, "KILL %lu", mysql->thread_id); if (mysql_real_query(kill_mysql, kill_buffer, (ulong)kill_buffer_length)) diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index a3b9bbd4f7e..2186ee60db1 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -905,7 +905,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, */ collect_eis= (table->table->s->table_category == TABLE_CATEGORY_USER && - !(lex->alter_info.flags & ALTER_PARTITION_ADMIN) && + !(lex->alter_info.partition_flags & ALTER_PARTITION_ADMIN) && (check_eits_collection_allowed(thd) || lex->with_persistent_for_clause)); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 2b19f4506db..779146d2855 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -9213,6 +9213,9 @@ fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, @param values values to fill with @param ignore_errors TRUE if we should ignore errors @param use_value forces usage of value of the items instead of result + @param check_for_computability whether to check for ability to invoke val_*() + methods (val_int () etc) against supplied + values @details fill_record() may set table->auto_increment_field_not_null and a @@ -9226,7 +9229,7 @@ fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, bool fill_record(THD *thd, TABLE *table, Field **ptr, List &values, - bool ignore_errors, bool use_value) + bool ignore_errors, bool use_value, bool check_for_computability) { List_iterator_fast v(values); List tbl_list; @@ -9266,6 +9269,10 @@ fill_record(THD *thd, TABLE *table, Field **ptr, List &values, /* Ensure the end of the list of values is not reached */ DBUG_ASSERT(value); + if (check_for_computability && + value->check_is_evaluable_expression_or_error()) + goto err; + const bool skip_sys_field= field->vers_sys_field() && !thd->vers_insert_history_fast(table); @@ -9342,7 +9349,7 @@ fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, Field **ptr, bool result; Table_triggers_list *triggers= table->triggers; - result= fill_record(thd, table, ptr, values, ignore_errors, FALSE); + result= fill_record(thd, table, ptr, values, ignore_errors, false, false); if (!result && triggers && *ptr) result= triggers->process_triggers(thd, event, TRG_ACTION_BEFORE, TRUE) || diff --git a/sql/sql_base.h b/sql/sql_base.h index 020db60c4fc..bd3984dd292 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -194,7 +194,8 @@ void unfix_fields(List &items); bool fill_record(THD * thd, TABLE *table_arg, List &fields, List &values, bool ignore_errors, bool update); bool fill_record(THD *thd, TABLE *table, Field **field, List &values, - bool ignore_errors, bool use_value); + bool ignore_errors, bool use_value, + bool check_for_evaluability); Field * find_field_in_tables(THD *thd, Item_ident *item, diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 3cb2ab1b814..086623633ca 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -5706,6 +5706,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_delete.cc b/sql/sql_delete.cc index 6b2d8880b3d..c3c2109690c 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -263,7 +263,10 @@ int update_portion_of_time(THD *thd, TABLE *table, res= src->save_in_field(table->field[dst_fieldno], true); if (likely(!res)) + { + table->period_prepare_autoinc(); res= table->update_generated_fields(); + } if(likely(!res)) res= table->file->ha_update_row(table->record[1], table->record[0]); diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 54a1aae0816..f56ce08aee0 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -1241,7 +1241,9 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) /* Execute the query that specifies the derived table by a foreign engine */ res= derived->pushdown_derived->execute(); unit->executed= true; + if (res) DBUG_RETURN(res); + goto after_exec; } if (unit->executed && !derived_is_recursive && @@ -1302,6 +1304,7 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) derived_result, unit, first_select); } + after_exec: if (!res && !derived_is_recursive) { if (derived_result->flush()) diff --git a/sql/sql_expression_cache.cc b/sql/sql_expression_cache.cc index 8681e08e014..8b511b25939 100644 --- a/sql/sql_expression_cache.cc +++ b/sql/sql_expression_cache.cc @@ -272,7 +272,8 @@ my_bool Expression_cache_tmptable::put_value(Item *value) } *(items.head_ref())= value; - fill_record(table_thd, cache_table, cache_table->field, items, TRUE, TRUE); + fill_record(table_thd, cache_table, cache_table->field, items, true, true, + true); if (unlikely(table_thd->is_error())) goto err;; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 08181835dba..84b253bad75 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -107,23 +107,41 @@ public: class Wsrep_load_data_split { public: - Wsrep_load_data_split(THD *thd) + Wsrep_load_data_split(THD *thd, TABLE *table) : m_thd(thd) - , m_load_data_splitting(wsrep_load_data_splitting) + , m_load_data_splitting(false) , m_fragment_unit(thd->wsrep_trx().streaming_context().fragment_unit()) , m_fragment_size(thd->wsrep_trx().streaming_context().fragment_size()) { - if (WSREP(m_thd) && m_load_data_splitting) + /* + We support load data splitting for InnoDB only as it will use + streaming replication (SR). + */ + if (WSREP(thd) && wsrep_load_data_splitting) { - /* Override streaming settings with backward compatible values for - load data splitting */ - m_thd->wsrep_cs().streaming_params(wsrep::streaming_context::row, 10000); + handlerton *ht= table->s->db_type(); + // For partitioned tables find underlying hton + if (table->file->partition_ht()) + ht= table->file->partition_ht(); + if (ht->db_type != DB_TYPE_INNODB) + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_NOT_SUPPORTED_YET, + "wsrep_load_data_splitting for other than InnoDB tables"); + } + else + { + /* Override streaming settings with backward compatible values for + load data splitting */ + m_thd->wsrep_cs().streaming_params(wsrep::streaming_context::row, 10000); + m_load_data_splitting= true; + } } } ~Wsrep_load_data_split() { - if (WSREP(m_thd) && m_load_data_splitting) + if (m_load_data_splitting) { /* Restore original settings */ m_thd->wsrep_cs().streaming_params(m_fragment_unit, m_fragment_size); @@ -348,6 +366,7 @@ int mysql_load(THD *thd, const sql_exchange *ex, TABLE_LIST *table_list, bool is_concurrent; #endif const char *db= table_list->db.str; // This is never null + /* If path for file is not defined, we will use the current database. If this is not set, we will use the directory where the table to be @@ -358,9 +377,6 @@ int mysql_load(THD *thd, const sql_exchange *ex, TABLE_LIST *table_list, bool transactional_table __attribute__((unused)); DBUG_ENTER("mysql_load"); -#ifdef WITH_WSREP - Wsrep_load_data_split wsrep_load_data_split(thd); -#endif /* WITH_WSREP */ /* Bug #34283 mysqlbinlog leaves tmpfile after termination if binlog contains @@ -425,6 +441,11 @@ int mysql_load(THD *thd, const sql_exchange *ex, TABLE_LIST *table_list, { DBUG_RETURN(TRUE); } + +#ifdef WITH_WSREP + Wsrep_load_data_split wsrep_load_data_split(thd, table_list->table); +#endif /* WITH_WSREP */ + thd_proc_info(thd, "Executing"); /* Let us emit an error if we are loading data to table which is used diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a27eca72a03..7a2f3286f82 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4649,10 +4649,15 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt) if ((res= insert_precheck(thd, all_tables))) break; + #ifdef WITH_WSREP - if (WSREP(thd) && thd->wsrep_consistency_check == CONSISTENCY_CHECK_DECLARED) + bool wsrep_toi= false; + const bool wsrep= WSREP(thd); + + if (wsrep && thd->wsrep_consistency_check == CONSISTENCY_CHECK_DECLARED) { thd->wsrep_consistency_check = CONSISTENCY_CHECK_RUNNING; + wsrep_toi= true; WSREP_TO_ISOLATION_BEGIN(first_table->db.str, first_table->table_name.str, NULL); } #endif /* WITH_WSREP */ @@ -4687,6 +4692,27 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt) if (!(res=open_and_lock_tables(thd, all_tables, TRUE, 0))) { MYSQL_INSERT_SELECT_START(thd->query()); + +#ifdef WITH_WSREP + if (wsrep && !first_table->view) + { + bool is_innodb= (first_table->table->file->ht->db_type == DB_TYPE_INNODB); + + // For consistency check inserted table needs to be InnoDB + if (!is_innodb && thd->wsrep_consistency_check != NO_CONSISTENCY_CHECK) + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + HA_ERR_UNSUPPORTED, + "Galera cluster does support consistency check only" + " for InnoDB tables."); + thd->wsrep_consistency_check= NO_CONSISTENCY_CHECK; + } + + // For !InnoDB we start TOI if it is not yet started and hope for the best + if (!is_innodb && !wsrep_toi) + WSREP_TO_ISOLATION_BEGIN(first_table->db.str, first_table->table_name.str, NULL); + } +#endif /* WITH_WSREP */ /* Only the INSERT table should be merged. Other will be handled by select. diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 49b58dec4ee..412924fde86 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1505,7 +1505,7 @@ static int plugin_initialize(MEM_ROOT *tmp_root, struct st_plugin_int *plugin, else ret= plugin_do_initialize(plugin, state); - if (ret) + if (ret && ret != HA_ERR_RETRY_INIT) plugin_variables_deinit(plugin); mysql_mutex_lock(&LOCK_plugin); @@ -1786,6 +1786,7 @@ int plugin_init(int *argc, char **argv, int flags) uint state= plugin_ptr->state; mysql_mutex_unlock(&LOCK_plugin); error= plugin_do_initialize(plugin_ptr, state); + DBUG_EXECUTE_IF("fail_spider_init_retry", error= 1;); mysql_mutex_lock(&LOCK_plugin); plugin_ptr->state= state; if (error == HA_ERR_RETRY_INIT) diff --git a/sql/sql_plugin_services.inl b/sql/sql_plugin_services.inl index 5ac06e76e85..b291bf5c246 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 +}; + static struct json_service_st json_handler= { json_type, @@ -336,6 +342,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/sql/sql_select.cc b/sql/sql_select.cc index 4268888849b..9b964fd87bb 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -323,8 +323,6 @@ static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table); static void copy_sum_funcs(Item_sum **func_ptr, Item_sum **end); static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab); static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr); -static bool prepare_sum_aggregators(THD *thd, Item_sum **func_ptr, - bool need_distinct); static bool init_sum_functions(Item_sum **func, Item_sum **end); static bool update_sum_func(Item_sum **func); static void select_describe(JOIN *join, bool need_tmp_table,bool need_order, @@ -2399,6 +2397,10 @@ JOIN::optimize_inner() select_lex->attach_to_conds, &cond_value); sel->attach_to_conds.empty(); + Json_writer_object wrapper(thd); + Json_writer_object pushd(thd, "condition_pushdown_from_having"); + pushd.add("conds", conds); + pushd.add("having", having); } } @@ -4286,7 +4288,7 @@ JOIN::create_postjoin_aggr_table(JOIN_TAB *tab, List *table_fields, if (make_sum_func_list(all_fields, fields_list, true)) goto err; if (prepare_sum_aggregators(thd, sum_funcs, - !(tables_list && + !(tables_list && join_tab->is_using_agg_loose_index_scan()))) goto err; if (setup_sum_funcs(thd, sum_funcs)) @@ -14862,7 +14864,8 @@ end_sj_materialize(JOIN *join, JOIN_TAB *join_tab, bool end_of_records) if (item->is_null()) DBUG_RETURN(NESTED_LOOP_OK); } - fill_record(thd, table, table->field, sjm->sjm_table_cols, TRUE, FALSE); + fill_record(thd, table, table->field, sjm->sjm_table_cols, true, false, + true); if (unlikely(thd->is_error())) DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */ if (unlikely((error= table->file->ha_write_tmp_row(table->record[0])))) @@ -28905,15 +28908,86 @@ static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr) } -static bool prepare_sum_aggregators(THD *thd,Item_sum **func_ptr, - bool need_distinct) +/* + @brief + Setup aggregate functions. + + @param thd Thread descriptor + @param func_ptr Array of pointers to aggregate functions + @param need_distinct FALSE means that the table access method already + guarantees that arguments of all aggregate functions + will be unique. (This is the case for Loose Scan) + TRUE - Otherwise. + @return + false Ok + true Error +*/ + +bool JOIN::prepare_sum_aggregators(THD *thd, Item_sum **func_ptr, + bool need_distinct) { Item_sum *func; DBUG_ENTER("prepare_sum_aggregators"); while ((func= *(func_ptr++))) { - if (func->set_aggregator(thd, - need_distinct && func->has_with_distinct() ? + bool need_distinct_aggregator= need_distinct && func->has_with_distinct(); + if (need_distinct_aggregator && table_count - const_tables == 1) + { + /* + We are doing setup for an aggregate with DISTINCT, like + + SELECT agg_func(DISTINCT col1, col2 ...) FROM ... + + In general case, agg_func will need to use Aggregator_distinct to + remove duplicates from its arguments. + We won't have to remove duplicates if we know the arguments are already + unique. This is true when + 1. the join operation has only one non-const table (checked above) + 2. the argument list covers a PRIMARY or a UNIQUE index. + + Example: here the values of t1.pk are unique: + + SELECT agg_func(DISTINCT t1.pk, ...) FROM t1 + + and so the whole argument of agg_func is unique. + */ + List arg_fields; + for (uint i= 0; i < func->argument_count(); i++) + { + if (func->arguments()[i]->real_item()->type() == Item::FIELD_ITEM) + arg_fields.push_back(func->arguments()[i]); + } + + /* + If the query has a GROUP BY, then it's sufficient that a unique + key is covered by a concatenation of {argument_list, group_by_list}. + + Example: Suppose t1 has PRIMARY KEY(pk1, pk2). Then: + + SELECT agg_func(DISTINCT t1.pk1, ...) FROM t1 GROUP BY t1.pk2 + + Each GROUP BY group will have t1.pk2 fixed. Then, the values of t1.pk1 + will be unique, and no de-duplication will be needed. + */ + for (ORDER *group= group_list; group ; group= group->next) + { + if ((*group->item)->real_item()->type() == Item::FIELD_ITEM) + arg_fields.push_back(*group->item); + } + + if (list_contains_unique_index(join_tab[const_tables].table, + find_field_in_item_list, + (void *) &arg_fields)) + need_distinct_aggregator= false; + } + Json_writer_object trace_wrapper(thd); + Json_writer_object trace_aggr(thd, "prepare_sum_aggregators"); + trace_aggr.add("function", func); + trace_aggr.add("aggregator_type", + (need_distinct_aggregator || + func->uses_non_standard_aggregator_for_distinct()) ? + "distinct" : "simple"); + if (func->set_aggregator(thd, need_distinct_aggregator ? Aggregator::DISTINCT_AGGREGATOR : Aggregator::SIMPLE_AGGREGATOR)) DBUG_RETURN(TRUE); diff --git a/sql/sql_select.h b/sql/sql_select.h index eae74dc9a3b..7506c95461c 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1955,6 +1955,8 @@ private: bool add_fields_for_current_rowid(JOIN_TAB *cur, List *fields); void free_pushdown_handlers(List& join_list); void init_join_cache_and_keyread(); + bool prepare_sum_aggregators(THD *thd,Item_sum **func_ptr, + bool need_distinct); bool transform_in_predicates_into_equalities(THD *thd); bool transform_all_conds_and_on_exprs(THD *thd, Item_transformer transformer); diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc index f6d7c310a2f..b1d59aac984 100644 --- a/sql/sql_sequence.cc +++ b/sql/sql_sequence.cc @@ -28,6 +28,9 @@ #include "sql_acl.h" #ifdef WITH_WSREP #include "wsrep_mysqld.h" +bool wsrep_check_sequence(THD* thd, + const sequence_definition *seq, + const bool used_engine); #endif struct Field_definition @@ -942,7 +945,8 @@ bool Sql_cmd_alter_sequence::execute(THD *thd) #ifdef WITH_WSREP if (WSREP(thd) && wsrep_thd_is_local(thd)) { - if (wsrep_check_sequence(thd, new_seq)) + const bool used_engine= lex->create_info.used_fields & HA_CREATE_USED_ENGINE; + if (wsrep_check_sequence(thd, new_seq, used_engine)) DBUG_RETURN(TRUE); if (wsrep_to_isolation_begin(thd, first_table->db.str, diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 67bc3806ff2..896cd347c62 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3030,7 +3030,7 @@ int select_result_explain_buffer::send_data(List &items) Show_explain_request::call_in_target_thread, is this necessary anymore?) */ set_current_thd(thd); - fill_record(thd, dst_table, dst_table->field, items, TRUE, FALSE); + fill_record(thd, dst_table, dst_table->field, items, true, false, false); res= dst_table->file->ha_write_tmp_row(dst_table->record[0]); set_current_thd(cur_thd); DBUG_RETURN(MY_TEST(res)); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 0fc80fb18da..82fa163e026 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4805,18 +4805,21 @@ int mysql_create_table_no_lock(THD *thd, #ifdef WITH_WSREP /** Additional sequence checks for Galera cluster. -@param thd thread handle -@param seq sequence definition +@param thd thread handle +@param seq sequence definition +@param used_engine create used ENGINE= @retval false success @retval true failure */ -bool wsrep_check_sequence(THD* thd, const sequence_definition *seq) +bool wsrep_check_sequence(THD* thd, + const sequence_definition *seq, + const bool used_engine) { enum legacy_db_type db_type; DBUG_ASSERT(WSREP(thd)); - if (thd->lex->create_info.used_fields & HA_CREATE_USED_ENGINE) + if (used_engine) { db_type= thd->lex->create_info.db_type->db_type; } @@ -4847,6 +4850,57 @@ bool wsrep_check_sequence(THD* thd, const sequence_definition *seq) return (false); } + +/** Additional CREATE TABLE/SEQUENCE checks for Galera cluster. + +@param thd thread handle +@param wsrep_ctas CREATE TABLE AS SELECT ? +@param used_engine CREATE TABLE ... ENGINE = ? +@param create_info Create information + +@retval false Galera cluster does support used clause +@retval true Galera cluster does not support used clause +*/ +static +bool wsrep_check_support(THD* thd, + const bool wsrep_ctas, + const bool used_engine, + const HA_CREATE_INFO* create_info) +{ + /* CREATE TABLE ... AS SELECT */ + if (wsrep_ctas && + thd->variables.wsrep_trx_fragment_size > 0) + { + my_message(ER_NOT_ALLOWED_COMMAND, + "CREATE TABLE AS SELECT is not supported with streaming replication", + MYF(0)); + return true; + } + /* CREATE TABLE .. WITH SYSTEM VERSIONING AS SELECT + is not supported in Galera cluster. + */ + if (wsrep_ctas && + create_info->versioned()) + { + my_error(ER_NOT_SUPPORTED_YET, MYF(0), + "SYSTEM VERSIONING AS SELECT in Galera cluster"); + return true; + } + /* + CREATE TABLE ... ENGINE=SEQUENCE is not supported in + Galera cluster. + CREATE SEQUENCE ... ENGINE=xxx Galera cluster supports + only InnoDB-sequences. + */ + if (((used_engine && create_info->db_type && + (create_info->db_type->db_type == DB_TYPE_SEQUENCE || + create_info->db_type->db_type >= DB_TYPE_FIRST_DYNAMIC)) || + thd->lex->sql_command == SQLCOM_CREATE_SEQUENCE) && + wsrep_check_sequence(thd, create_info->seq_create_info, used_engine)) + return true; + + return false; +} #endif /* WITH_WSREP */ /** @@ -4922,15 +4976,6 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table, if (!(thd->variables.option_bits & OPTION_EXPLICIT_DEF_TIMESTAMP)) promote_first_timestamp_column(&alter_info->create_list); -#ifdef WITH_WSREP - if (thd->lex->sql_command == SQLCOM_CREATE_SEQUENCE && - WSREP(thd) && wsrep_thd_is_local_toi(thd)) - { - if (wsrep_check_sequence(thd, create_info->seq_create_info)) - DBUG_RETURN(true); - } -#endif /* WITH_WSREP */ - /* We can abort create table for any table type */ thd->abort_on_warning= thd->is_strict_mode(); @@ -10096,6 +10141,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, TODO: this design is obsolete and will be removed. */ int table_kind= check_if_log_table(table_list, FALSE, NullS); + const bool used_engine= create_info->used_fields & HA_CREATE_USED_ENGINE; if (table_kind) { @@ -10107,7 +10153,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, } /* Disable alter of log tables to unsupported engine */ - if ((create_info->used_fields & HA_CREATE_USED_ENGINE) && + if ((used_engine) && (!create_info->db_type || /* unknown engine */ !(create_info->db_type->flags & HTON_SUPPORT_LOG_TABLES))) { @@ -10197,7 +10243,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, if we can support implementing storage engine. */ if (WSREP(thd) && table && table->s->sequence && - wsrep_check_sequence(thd, thd->lex->create_info.seq_create_info)) + wsrep_check_sequence(thd, thd->lex->create_info.seq_create_info, used_engine)) DBUG_RETURN(TRUE); if (WSREP(thd) && @@ -10702,12 +10748,10 @@ do_continue:; #endif #ifdef WITH_WSREP + // ALTER TABLE for sequence object, check can we support it if (table->s->sequence && WSREP(thd) && - wsrep_thd_is_local_toi(thd)) - { - if (wsrep_check_sequence(thd, create_info->seq_create_info)) + wsrep_check_sequence(thd, create_info->seq_create_info, used_engine)) DBUG_RETURN(TRUE); - } #endif /* WITH_WSREP */ /* @@ -12502,17 +12546,11 @@ bool Sql_cmd_create_table_like::execute(THD *thd) #endif #ifdef WITH_WSREP - if (wsrep_ctas) + if (WSREP(thd) && + wsrep_check_support(thd, wsrep_ctas, used_engine, &create_info)) { - if (thd->variables.wsrep_trx_fragment_size > 0) - { - my_message( - ER_NOT_ALLOWED_COMMAND, - "CREATE TABLE AS SELECT is not supported with streaming replication", - MYF(0)); - res= 1; - goto end_with_restore_list; - } + res= 1; + goto end_with_restore_list; } #endif /* WITH_WSREP */ @@ -12664,6 +12702,7 @@ bool Sql_cmd_create_table_like::execute(THD *thd) create_table->table_name, create_table->db)) goto end_with_restore_list; +#ifdef WITH_WSREP /* In STATEMENT format, we probably have to replicate also temporary tables, like mysql replication does. Also check if the requested @@ -12672,15 +12711,15 @@ bool Sql_cmd_create_table_like::execute(THD *thd) if (WSREP(thd)) { handlerton *orig_ht= create_info.db_type; + if (!check_engine(thd, create_table->db.str, create_table->table_name.str, &create_info) && (!thd->is_current_stmt_binlog_format_row() || !create_info.tmp_table())) { -#ifdef WITH_WSREP if (thd->lex->sql_command == SQLCOM_CREATE_SEQUENCE && - wsrep_check_sequence(thd, lex->create_info.seq_create_info)) + wsrep_check_sequence(thd, lex->create_info.seq_create_info, used_engine)) DBUG_RETURN(true); WSREP_TO_ISOLATION_BEGIN_ALTER(create_table->db.str, @@ -12691,14 +12730,15 @@ bool Sql_cmd_create_table_like::execute(THD *thd) WSREP_WARN("CREATE TABLE isolation failure"); res= true; goto end_with_restore_list; - } -#endif /* WITH_WSREP */ + } } // check_engine will set db_type to NULL if e.g. TEMPORARY is // not supported by the storage engine, this case is checked // again in mysql_create_table create_info.db_type= orig_ht; } +#endif /* WITH_WSREP */ + /* Regular CREATE TABLE */ res= mysql_create_table(thd, create_table, &create_info, &alter_info); } diff --git a/sql/sql_table.h b/sql/sql_table.h index fded83531f5..a75fa58a7e0 100644 --- a/sql/sql_table.h +++ b/sql/sql_table.h @@ -216,8 +216,4 @@ extern MYSQL_PLUGIN_IMPORT const LEX_CSTRING primary_key_name; bool check_engine(THD *, const char *, const char *, HA_CREATE_INFO *); -#ifdef WITH_WSREP -bool wsrep_check_sequence(THD* thd, const class sequence_definition *seq); -#endif - #endif /* SQL_TABLE_INCLUDED */ diff --git a/sql/sql_udf.h b/sql/sql_udf.h index cb1954353fa..5bd2c6e5445 100644 --- a/sql/sql_udf.h +++ b/sql/sql_udf.h @@ -147,6 +147,20 @@ class udf_handler :public Sql_alloc *null_value= (my_bool) (is_null || error); } String *val_str(String *str,String *save_str); + + udf_handler(const udf_handler &orig) + { + u_d = orig.u_d; + buffers = orig.buffers; + f_args = orig.f_args; + initid = orig.initid; + num_buffer = orig.num_buffer; + error = orig.error; + is_null = orig.is_null; + initialized = orig.initialized; + args = orig.args; + not_original = true; + } }; diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 7d4bf72883d..86363880fd4 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -116,12 +116,12 @@ int select_unit::send_data(List &values) if (table->no_rows_with_nulls) table->null_catch_flags= CHECK_ROW_FOR_NULLS_TO_REJECT; - fill_record(thd, table, table->field + addon_cnt, values, true, false); + fill_record(thd, table, table->field + addon_cnt, values, true, false, true); /* set up initial values for records to be written */ if (addon_cnt && step == UNION_TYPE) { DBUG_ASSERT(addon_cnt == 1); - table->field[0]->store((longlong) curr_step, 1); + table->field[0]->store((ulonglong) curr_step, 1); } if (unlikely(thd->is_error())) @@ -614,7 +614,7 @@ int select_unit_ext::send_data(List &values) if (table->no_rows_with_nulls) table->null_catch_flags= CHECK_ROW_FOR_NULLS_TO_REJECT; - fill_record(thd, table, table->field + addon_cnt, values, true, false); + fill_record(thd, table, table->field + addon_cnt, values, true, false, true); /* set up initial values for records to be written */ if ( step == UNION_TYPE ) { @@ -998,7 +998,7 @@ int select_union_direct::send_data(List &items) } send_records++; - fill_record(thd, table, table->field, items, true, false); + fill_record(thd, table, table->field, items, true, false, true); if (unlikely(thd->is_error())) return true; /* purecov: inspected */ diff --git a/sql/sql_update.cc b/sql/sql_update.cc index f1391be633f..b948c2e46fc 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -2182,6 +2182,10 @@ int multi_update::prepare(List ¬_used_values, { Item *value= value_it++; uint offset= item->field->table->pos_in_table_list->shared; + + if (value->associate_with_target_field(thd, item)) + DBUG_RETURN(1); + fields_for_table[offset]->push_back(item, thd->mem_root); values_for_table[offset]->push_back(value, thd->mem_root); } @@ -2681,7 +2685,7 @@ int multi_update::send_data(List ¬_used_values) tmp_table_param[offset].func_count); fill_record(thd, tmp_table, tmp_table->field + 1 + unupdated_check_opt_tables.elements, - *values_for_table[offset], TRUE, FALSE); + *values_for_table[offset], true, false, false); /* Write row, ignoring duplicated updates to a row */ error= tmp_table->file->ha_write_tmp_row(tmp_table->record[0]); diff --git a/sql/table.cc b/sql/table.cc index 92d0d6d16aa..7862e6217ea 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -9313,10 +9313,9 @@ int TABLE::update_default_fields(bool ignore_errors) int TABLE::update_generated_fields() { int res= 0; - if (found_next_number_field) + if (next_number_field) { - next_number_field= found_next_number_field; - res= found_next_number_field->set_default(); + res= next_number_field->set_default(); if (likely(!res)) res= file->update_auto_increment(); next_number_field= NULL; @@ -9331,6 +9330,18 @@ int TABLE::update_generated_fields() return res; } +void TABLE::period_prepare_autoinc() +{ + if (!found_next_number_field) + return; + /* Don't generate a new value if the autoinc index is WITHOUT OVERLAPS */ + DBUG_ASSERT(s->next_number_index != (uint)-1); + if (key_info[s->next_number_index].without_overlaps) + return; + + next_number_field= found_next_number_field; +} + int TABLE::period_make_insert(Item *src, Field *dst) { THD *thd= in_use; @@ -9340,7 +9351,10 @@ int TABLE::period_make_insert(Item *src, Field *dst) int res= src->save_in_field(dst, true); if (likely(!res)) + { + period_prepare_autoinc(); res= update_generated_fields(); + } if (likely(!res) && triggers) res= triggers->process_triggers(thd, TRG_EVENT_INSERT, diff --git a/sql/table.h b/sql/table.h index 16a39d6f690..e409cc89475 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1908,6 +1908,7 @@ public: #endif int update_generated_fields(); + void period_prepare_autoinc(); int period_make_insert(Item *src, Field *dst); int insert_portion_of_time(THD *thd, const vers_select_conds_t &period_conds, ha_rows *rows_inserted); diff --git a/sql/unireg.cc b/sql/unireg.cc index ea0b94eb022..05a4fbb1fbe 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -806,7 +806,15 @@ static bool pack_vcols(THD *thd, String *buf, List &create_fields, ? VCOL_GENERATED_STORED : VCOL_GENERATED_VIRTUAL)) return 1; if (field->has_default_expression() && !field->has_default_now_unireg_check()) - if (pack_expression(buf, field->default_value, field_nr, VCOL_DEFAULT)) + if (pack_expression(buf, field->default_value, field_nr, VCOL_DEFAULT) || + /* + field->has_default_expression() can return error (e.g. because + the method Item_param::basic_const_item invokes + invalid_default_param() + in case either DEFAULT_VALUE or IGNORE_VALUE is handled). + Take this fact into account and return error in this case. + */ + thd->is_error()) return 1; if (field->check_constraint) if (pack_expression(buf, field->check_constraint, field_nr, diff --git a/storage/connect/libdoc.cpp b/storage/connect/libdoc.cpp index 67f22ce29e9..ab588dd49a6 100644 --- a/storage/connect/libdoc.cpp +++ b/storage/connect/libdoc.cpp @@ -93,7 +93,6 @@ class LIBXMLDOC : public XMLDOCUMENT { xmlXPathContextPtr Ctxp; xmlXPathObjectPtr Xop; xmlXPathObjectPtr NlXop; - xmlErrorPtr Xerr; char *Buf; // Temporary bool Nofreelist; }; // end of class LIBXMLDOC @@ -327,7 +326,6 @@ LIBXMLDOC::LIBXMLDOC(char *nsl, char *nsdf, char *enc, PFBLOCK fp) Ctxp = NULL; Xop = NULL; NlXop = NULL; - Xerr = NULL; Buf = NULL; Nofreelist = false; } // end of LIBXMLDOC constructor @@ -365,8 +363,8 @@ bool LIBXMLDOC::ParseFile(PGLOBAL g, char *fn) Encoding = (char*)Docp->encoding; return false; - } else if ((Xerr = xmlGetLastError())) - xmlResetError(Xerr); + } else if (xmlGetLastError()) + xmlResetLastError(); return true; } // end of ParseFile @@ -505,9 +503,9 @@ int LIBXMLDOC::DumpDoc(PGLOBAL g, char *ofn) #if 1 // This function does not crash ( if (xmlSaveFormatFileEnc((const char *)ofn, Docp, Encoding, 0) < 0) { - xmlErrorPtr err = xmlGetLastError(); + const xmlError *err = xmlGetLastError(); strcpy(g->Message, (err) ? err->message : "Error saving XML doc"); - xmlResetError(Xerr); + xmlResetLastError(); rc = -1; } // endif Save // rc = xmlDocDump(of, Docp); @@ -546,8 +544,8 @@ void LIBXMLDOC::CloseDoc(PGLOBAL g, PFBLOCK xp) if (Nlist) { xmlXPathFreeNodeSet(Nlist); - if ((Xerr = xmlGetLastError())) - xmlResetError(Xerr); + if (xmlGetLastError()) + xmlResetLastError(); Nlist = NULL; } // endif Nlist @@ -555,8 +553,8 @@ void LIBXMLDOC::CloseDoc(PGLOBAL g, PFBLOCK xp) if (Xop) { xmlXPathFreeObject(Xop); - if ((Xerr = xmlGetLastError())) - xmlResetError(Xerr); + if (xmlGetLastError()) + xmlResetLastError(); Xop = NULL; } // endif Xop @@ -564,8 +562,8 @@ void LIBXMLDOC::CloseDoc(PGLOBAL g, PFBLOCK xp) if (NlXop) { xmlXPathFreeObject(NlXop); - if ((Xerr = xmlGetLastError())) - xmlResetError(Xerr); + if (xmlGetLastError()) + xmlResetLastError(); NlXop = NULL; } // endif NlXop @@ -573,8 +571,8 @@ void LIBXMLDOC::CloseDoc(PGLOBAL g, PFBLOCK xp) if (Ctxp) { xmlXPathFreeContext(Ctxp); - if ((Xerr = xmlGetLastError())) - xmlResetError(Xerr); + if (xmlGetLastError()) + xmlResetLastError(); Ctxp = NULL; } // endif Ctxp @@ -590,6 +588,7 @@ void LIBXMLDOC::CloseDoc(PGLOBAL g, PFBLOCK xp) /******************************************************************/ xmlNodeSetPtr LIBXMLDOC::GetNodeList(PGLOBAL g, xmlNodePtr np, char *xp) { + const xmlError *xerr; xmlNodeSetPtr nl; if (trace(1)) @@ -649,11 +648,11 @@ xmlNodeSetPtr LIBXMLDOC::GetNodeList(PGLOBAL g, xmlNodePtr np, char *xp) } else xmlXPathFreeObject(Xop); // Caused node not found - if ((Xerr = xmlGetLastError())) { - strcpy(g->Message, Xerr->message); - xmlResetError(Xerr); + if ((xerr = xmlGetLastError())) { + strcpy(g->Message, xerr->message); + xmlResetLastError(); return NULL; - } // endif Xerr + } // endif xerr } // endif Xop @@ -1079,7 +1078,7 @@ void XML2NODE::AddText(PGLOBAL g, PCSZ txtp) /******************************************************************/ void XML2NODE::DeleteChild(PGLOBAL g, PXNODE dnp) { - xmlErrorPtr xerr; + const xmlError *xerr; if (trace(1)) htrc("DeleteChild: node=%p\n", dnp); @@ -1122,7 +1121,7 @@ err: if (trace(1)) htrc("DeleteChild: errmsg=%-.256s\n", xerr->message); - xmlResetError(xerr); + xmlResetLastError(); } // end of DeleteChild /* -------------------- class XML2NODELIST ---------------------- */ diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 7941c131cc0..af774d84d1f 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -1158,54 +1158,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/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 6fd93469d3e..cd1012f3820 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -657,47 +657,22 @@ dict_table_t::parse_name<>(char(&)[NAME_LEN + 1], char(&)[NAME_LEN + 1], /** Acquire MDL shared for the table name. @tparam trylock whether to use non-blocking operation @param[in,out] table table object -@param[in,out] thd background thread -@param[out] mdl mdl ticket +@param[in,out] mdl_context MDL context +@param[out] mdl MDL ticket @param[in] table_op operation to perform when opening @return table object after locking MDL shared @retval nullptr if the table is not readable, or if trylock && MDL blocked */ template +__attribute__((nonnull, warn_unused_result)) dict_table_t* dict_acquire_mdl_shared(dict_table_t *table, - THD *thd, - MDL_ticket **mdl, + MDL_context *mdl_context, MDL_ticket **mdl, dict_table_op_t table_op) { - if (!table || !mdl) - return table; - - MDL_context *mdl_context= static_cast(thd_mdl_context(thd)); - size_t db_len; - dict_table_t *not_found= nullptr; - - if (trylock) - { - dict_sys.freeze(SRW_LOCK_CALL); - db_len= dict_get_db_name_len(table->name.m_name); - dict_sys.unfreeze(); - } - else - { - ut_ad(dict_sys.frozen_not_locked()); - db_len= dict_get_db_name_len(table->name.m_name); - } - - if (db_len == 0) - return table; /* InnoDB system tables are not covered by MDL */ - - if (!mdl_context) - return nullptr; - table_id_t table_id= table->id; char db_buf[NAME_LEN + 1], db_buf1[NAME_LEN + 1]; char tbl_buf[NAME_LEN + 1], tbl_buf1[NAME_LEN + 1]; - size_t tbl_len; + size_t db_len, tbl_len; bool unaccessible= false; if (!table->parse_name(db_buf, tbl_buf, &db_len, &tbl_len)) @@ -768,7 +743,6 @@ retry: if (!table || !table->is_accessible()) { - table= nullptr; return_without_mdl: if (trylock) dict_sys.unfreeze(); @@ -777,7 +751,7 @@ return_without_mdl: mdl_context->release_lock(*mdl); *mdl= nullptr; } - return not_found; + return nullptr; } size_t db1_len, tbl1_len; @@ -814,6 +788,50 @@ return_without_mdl: goto retry; } +template dict_table_t* dict_acquire_mdl_shared +(dict_table_t*,MDL_context*,MDL_ticket**,dict_table_op_t); + +/** Acquire MDL shared for the table name. +@tparam trylock whether to use non-blocking operation +@param[in,out] table table object +@param[in,out] thd background thread +@param[out] mdl mdl ticket +@param[in] table_op operation to perform when opening +@return table object after locking MDL shared +@retval nullptr if the table is not readable, or if trylock && MDL blocked */ +template +dict_table_t* +dict_acquire_mdl_shared(dict_table_t *table, + THD *thd, + MDL_ticket **mdl, + dict_table_op_t table_op) +{ + if (!table || !mdl) + return table; + + MDL_context *mdl_context= static_cast(thd_mdl_context(thd)); + size_t db_len; + + if (trylock) + { + dict_sys.freeze(SRW_LOCK_CALL); + db_len= dict_get_db_name_len(table->name.m_name); + dict_sys.unfreeze(); + } + else + { + ut_ad(dict_sys.frozen_not_locked()); + db_len= dict_get_db_name_len(table->name.m_name); + } + + if (db_len == 0) + return table; /* InnoDB system tables are not covered by MDL */ + + return mdl_context + ? dict_acquire_mdl_shared(table, mdl_context, mdl, table_op) + : nullptr; +} + template dict_table_t* dict_acquire_mdl_shared (dict_table_t*,THD*,MDL_ticket**,dict_table_op_t); template dict_table_t* dict_acquire_mdl_shared @@ -960,9 +978,6 @@ void dict_sys_t::lock_wait(SRW_LOCK_ARGS(const char *file, unsigned line)) { latch.wr_lock(SRW_LOCK_ARGS(file, line)); latch_ex_wait_start.store(0, std::memory_order_relaxed); - ut_ad(!latch_readers); - ut_ad(!latch_ex); - ut_d(latch_ex= pthread_self()); return; } @@ -978,35 +993,36 @@ void dict_sys_t::lock_wait(SRW_LOCK_ARGS(const char *file, unsigned line)) ib::warn() << "A long wait (" << waited << " seconds) was observed for dict_sys.latch"; latch.wr_lock(SRW_LOCK_ARGS(file, line)); - ut_ad(!latch_readers); - ut_ad(!latch_ex); - ut_d(latch_ex= pthread_self()); } #ifdef UNIV_PFS_RWLOCK ATTRIBUTE_NOINLINE void dict_sys_t::unlock() { - ut_ad(latch_ex == pthread_self()); - ut_ad(!latch_readers); - ut_d(latch_ex= 0); latch.wr_unlock(); } ATTRIBUTE_NOINLINE void dict_sys_t::freeze(const char *file, unsigned line) { latch.rd_lock(file, line); - ut_ad(!latch_ex); - ut_d(latch_readers++); } ATTRIBUTE_NOINLINE void dict_sys_t::unfreeze() { - ut_ad(!latch_ex); - ut_ad(latch_readers--); latch.rd_unlock(); } #endif /* UNIV_PFS_RWLOCK */ +/** Report an error about failing to open a table. +@param name table name */ +static void dict_table_open_failed(const table_name_t &name) +{ + my_printf_error(ER_TABLE_CORRUPT, + "Table %`.*s.%`s is corrupted." + " Please drop the table and recreate.", + MYF(ME_ERROR_LOG), + int(name.dblen()), name.m_name, name.basename()); +} + /**********************************************************************//** Returns a table object and increments its open handle count. NOTE! This is a high-level function to be used mainly from outside the @@ -1039,18 +1055,20 @@ dict_table_open_on_name( if (!(ignore_err & ~DICT_ERR_IGNORE_FK_NOKEY) && !table->is_readable() && table->corrupted) { - ulint algo = table->space->get_compression_algo(); - if (algo <= PAGE_ALGORITHM_LAST && !fil_comp_algo_loaded(algo)) { - my_printf_error(ER_PROVIDER_NOT_LOADED, - "Table %s is compressed with %s, which is not currently loaded. " - "Please load the %s provider plugin to open the table", - MYF(ME_ERROR_LOG), table->name, - page_compression_algorithms[algo], page_compression_algorithms[algo]); - } else { - my_printf_error(ER_TABLE_CORRUPT, - "Table %s is corrupted. Please drop the table and recreate.", - MYF(ME_ERROR_LOG), table->name); - } + ulint algo= table->space->get_compression_algo(); + if (algo <= PAGE_ALGORITHM_LAST && !fil_comp_algo_loaded(algo)) + my_printf_error(ER_PROVIDER_NOT_LOADED, + "Table %`.*s.%`s is compressed with %s," + " which is not currently loaded. " + "Please load the %s provider plugin" + " to open the table", + MYF(ME_ERROR_LOG), + int(table->name.dblen()), table->name.m_name, + table->name.basename(), + page_compression_algorithms[algo], + page_compression_algorithms[algo]); + else + dict_table_open_failed(table->name); dict_sys.unfreeze(); DBUG_RETURN(nullptr); } @@ -1070,8 +1088,7 @@ dict_table_open_on_name( if (!(ignore_err & ~DICT_ERR_IGNORE_FK_NOKEY) && !table->is_readable() && table->corrupted) { - ib::error() << "Table " << table->name - << " is corrupted. Please drop the table and recreate."; + dict_table_open_failed(table->name); if (!dict_locked) dict_sys.unlock(); DBUG_RETURN(nullptr); diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 0775d939002..4d9a1d3a33f 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -2187,6 +2187,22 @@ fts_trx_row_get_new_state( return(result); } +/** Compare two doubly indirected pointers */ +static int fts_ptr2_cmp(const void *p1, const void *p2) +{ + const void *a= **static_cast(p1); + const void *b= **static_cast(p2); + return b > a ? -1 : a > b; +} + +/** Compare a singly indirected pointer to a doubly indirected one */ +static int fts_ptr1_ptr2_cmp(const void *p1, const void *p2) +{ + const void *a= *static_cast(p1); + const void *b= **static_cast(p2); + return b > a ? -1 : a > b; +} + /******************************************************************//** Create a savepoint instance. @return savepoint instance */ @@ -2209,8 +2225,8 @@ fts_savepoint_create( savepoint->name = mem_heap_strdup(heap, name); } - savepoint->tables = rbt_create( - sizeof(fts_trx_table_t*), fts_trx_table_cmp); + static_assert(!offsetof(fts_trx_table_t, table), "ABI"); + savepoint->tables = rbt_create(sizeof(fts_trx_table_t*), fts_ptr2_cmp); return(savepoint); } @@ -2258,6 +2274,19 @@ fts_trx_create( return(ftt); } +/** Compare two doc_id */ +static inline int doc_id_cmp(doc_id_t a, doc_id_t b) +{ + return b > a ? -1 : a > b; +} + +/** Compare two DOC_ID. */ +int fts_doc_id_cmp(const void *p1, const void *p2) +{ + return doc_id_cmp(*static_cast(p1), + *static_cast(p2)); +} + /******************************************************************//** Create an FTS trx table. @return FTS trx table */ @@ -2276,7 +2305,8 @@ fts_trx_table_create( ftt->table = table; ftt->fts_trx = fts_trx; - ftt->rows = rbt_create(sizeof(fts_trx_row_t), fts_trx_row_doc_id_cmp); + static_assert(!offsetof(fts_trx_row_t, doc_id), "ABI"); + ftt->rows = rbt_create(sizeof(fts_trx_row_t), fts_doc_id_cmp); return(ftt); } @@ -2300,7 +2330,8 @@ fts_trx_table_clone( ftt->table = ftt_src->table; ftt->fts_trx = ftt_src->fts_trx; - ftt->rows = rbt_create(sizeof(fts_trx_row_t), fts_trx_row_doc_id_cmp); + static_assert(!offsetof(fts_trx_row_t, doc_id), "ABI"); + ftt->rows = rbt_create(sizeof(fts_trx_row_t), fts_doc_id_cmp); /* Copy the rb tree values to the new savepoint. */ rbt_merge_uniq(ftt->rows, ftt_src->rows); @@ -2325,13 +2356,9 @@ fts_trx_init( { fts_trx_table_t* ftt; ib_rbt_bound_t parent; - ib_rbt_t* tables; - fts_savepoint_t* savepoint; - - savepoint = static_cast(ib_vector_last(savepoints)); - - tables = savepoint->tables; - rbt_search_cmp(tables, &parent, &table->id, fts_trx_table_id_cmp, NULL); + ib_rbt_t* tables = static_cast( + ib_vector_last(savepoints))->tables; + rbt_search_cmp(tables, &parent, &table, fts_ptr1_ptr2_cmp, nullptr); if (parent.result == 0) { fts_trx_table_t** fttp; @@ -3860,6 +3887,13 @@ fts_write_node( return(error); } +/** Sort an array of doc_id */ +void fts_doc_ids_sort(ib_vector_t *doc_ids) +{ + doc_id_t *const data= reinterpret_cast(doc_ids->data); + std::sort(data, data + doc_ids->used); +} + /*********************************************************************//** Add rows to the DELETED_CACHE table. @return DB_SUCCESS if all went well else error code*/ @@ -3881,7 +3915,7 @@ fts_sync_add_deleted_cache( ut_a(ib_vector_size(doc_ids) > 0); - ib_vector_sort(doc_ids, fts_doc_id_cmp); + fts_doc_ids_sort(doc_ids); info = pars_info_create(); @@ -5575,8 +5609,8 @@ fts_savepoint_rollback_last_stmt( l_ftt = rbt_value(fts_trx_table_t*, node); rbt_search_cmp( - s_tables, &parent, &(*l_ftt)->table->id, - fts_trx_table_id_cmp, NULL); + s_tables, &parent, &(*l_ftt)->table, + fts_ptr1_ptr2_cmp, nullptr); if (parent.result == 0) { fts_trx_table_t** s_ftt; diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc index fe31767d901..30889e5903c 100644 --- a/storage/innobase/fts/fts0opt.cc +++ b/storage/innobase/fts/fts0opt.cc @@ -1016,7 +1016,7 @@ fts_table_fetch_doc_ids( que_graph_free(graph); if (error == DB_SUCCESS) { - ib_vector_sort(doc_ids->doc_ids, fts_doc_id_cmp); + fts_doc_ids_sort(doc_ids->doc_ids); } if (alloc_bk_trx) { diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc index 9c92a1171cf..b8f220768a0 100644 --- a/storage/innobase/fts/fts0que.cc +++ b/storage/innobase/fts/fts0que.cc @@ -385,22 +385,6 @@ fts_query_terms_in_document( ulint* total); /*!< out: total words in document */ #endif -/******************************************************************** -Compare two fts_doc_freq_t doc_ids. -@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ -UNIV_INLINE -int -fts_freq_doc_id_cmp( -/*================*/ - const void* p1, /*!< in: id1 */ - const void* p2) /*!< in: id2 */ -{ - const fts_doc_freq_t* fq1 = (const fts_doc_freq_t*) p1; - const fts_doc_freq_t* fq2 = (const fts_doc_freq_t*) p2; - - return((int) (fq1->doc_id - fq2->doc_id)); -} - #if 0 /*******************************************************************//** Print the table used for calculating LCS. */ @@ -506,14 +490,11 @@ fts_query_compare_rank( if (r2->rank < r1->rank) { return(-1); } else if (r2->rank == r1->rank) { - if (r1->doc_id < r2->doc_id) { - return(1); - } else if (r1->doc_id > r2->doc_id) { - return(1); + return -1; } - return(0); + return r1->doc_id > r2->doc_id; } return(1); @@ -674,8 +655,9 @@ fts_query_add_word_freq( word_freq.doc_count = 0; + static_assert(!offsetof(fts_doc_freq_t, doc_id), "ABI"); word_freq.doc_freqs = rbt_create( - sizeof(fts_doc_freq_t), fts_freq_doc_id_cmp); + sizeof(fts_doc_freq_t), fts_doc_id_cmp); parent.last = rbt_add_node( query->word_freqs, &parent, &word_freq); @@ -1253,8 +1235,9 @@ fts_query_intersect( /* Create the rb tree that will hold the doc ids of the intersection. */ + static_assert(!offsetof(fts_ranking_t, doc_id), "ABI"); query->intersection = rbt_create( - sizeof(fts_ranking_t), fts_ranking_doc_id_cmp); + sizeof(fts_ranking_t), fts_doc_id_cmp); query->total_size += SIZEOF_RBT_CREATE; @@ -1540,8 +1523,9 @@ fts_merge_doc_ids( to create a new result set for fts_query_intersect(). */ if (query->oper == FTS_EXIST) { + static_assert(!offsetof(fts_ranking_t, doc_id), "ABI"); query->intersection = rbt_create( - sizeof(fts_ranking_t), fts_ranking_doc_id_cmp); + sizeof(fts_ranking_t), fts_doc_id_cmp); query->total_size += SIZEOF_RBT_CREATE; } @@ -3012,8 +2996,9 @@ fts_query_visitor( if (query->oper == FTS_EXIST) { ut_ad(query->intersection == NULL); + static_assert(!offsetof(fts_ranking_t, doc_id), "ABI"); query->intersection = rbt_create( - sizeof(fts_ranking_t), fts_ranking_doc_id_cmp); + sizeof(fts_ranking_t), fts_doc_id_cmp); query->total_size += SIZEOF_RBT_CREATE; } @@ -3123,8 +3108,8 @@ fts_ast_visit_sub_exp( /* Create new result set to store the sub-expression result. We will merge this result set with the parent after processing. */ - query->doc_ids = rbt_create(sizeof(fts_ranking_t), - fts_ranking_doc_id_cmp); + static_assert(!offsetof(fts_ranking_t, doc_id), "ABI"); + query->doc_ids = rbt_create(sizeof(fts_ranking_t), fts_doc_id_cmp); query->total_size += SIZEOF_RBT_CREATE; @@ -3661,8 +3646,9 @@ fts_query_prepare_result( result = static_cast( ut_zalloc_nokey(sizeof(*result))); + static_assert(!offsetof(fts_ranking_t, doc_id), "ABI"); result->rankings_by_id = rbt_create( - sizeof(fts_ranking_t), fts_ranking_doc_id_cmp); + sizeof(fts_ranking_t), fts_doc_id_cmp); query->total_size += sizeof(fts_result_t) + SIZEOF_RBT_CREATE; result_is_null = true; @@ -4038,7 +4024,7 @@ fts_query( DEBUG_SYNC_C("fts_deleted_doc_ids_append"); /* Sort the vector so that we can do a binary search over the ids. */ - ib_vector_sort(query.deleted->doc_ids, fts_doc_id_cmp); + fts_doc_ids_sort(query.deleted->doc_ids); /* Convert the query string to lower case before parsing. We own the ut_malloc'ed result and so remember to free it before return. */ @@ -4065,8 +4051,9 @@ fts_query( query.heap = mem_heap_create(128); /* Create the rb tree for the doc id (current) set. */ + static_assert(!offsetof(fts_ranking_t, doc_id), "ABI"); query.doc_ids = rbt_create( - sizeof(fts_ranking_t), fts_ranking_doc_id_cmp); + sizeof(fts_ranking_t), fts_doc_id_cmp); query.parser = index->parser; query.total_size += SIZEOF_RBT_CREATE; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 5ebf422787f..d28581d3d89 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[]; @@ -115,6 +118,7 @@ thread_local ha_handler_stats *mariadb_stats= &mariadb_dummy_stats; #include "snappy-c.h" #include +#include // TT_FOR_UPGRADE #define thd_get_trx_isolation(X) ((enum_tx_isolation)thd_tx_isolation(X)) @@ -5309,67 +5313,6 @@ test_normalize_table_name_low() } } } - -/********************************************************************* -Test ut_format_name(). */ -static -void -test_ut_format_name() -/*=================*/ -{ - char buf[NAME_LEN * 3]; - - struct { - const char* name; - ulint buf_size; - const char* expected; - } test_data[] = { - {"test/t1", sizeof(buf), "`test`.`t1`"}, - {"test/t1", 12, "`test`.`t1`"}, - {"test/t1", 11, "`test`.`t1"}, - {"test/t1", 10, "`test`.`t"}, - {"test/t1", 9, "`test`.`"}, - {"test/t1", 8, "`test`."}, - {"test/t1", 7, "`test`"}, - {"test/t1", 6, "`test"}, - {"test/t1", 5, "`tes"}, - {"test/t1", 4, "`te"}, - {"test/t1", 3, "`t"}, - {"test/t1", 2, "`"}, - {"test/t1", 1, ""}, - {"test/t1", 0, "BUF_NOT_CHANGED"}, - {"table", sizeof(buf), "`table`"}, - {"ta'le", sizeof(buf), "`ta'le`"}, - {"ta\"le", sizeof(buf), "`ta\"le`"}, - {"ta`le", sizeof(buf), "`ta``le`"}, - }; - - for (size_t i = 0; i < UT_ARR_SIZE(test_data); i++) { - - memcpy(buf, "BUF_NOT_CHANGED", strlen("BUF_NOT_CHANGED") + 1); - - char* ret; - - ret = ut_format_name(test_data[i].name, - buf, - test_data[i].buf_size); - - ut_a(ret == buf); - - if (strcmp(buf, test_data[i].expected) == 0) { - ib::info() << "ut_format_name(" << test_data[i].name - << ", buf, " << test_data[i].buf_size << ")," - " expected " << test_data[i].expected - << ", OK"; - } else { - ib::error() << "ut_format_name(" << test_data[i].name - << ", buf, " << test_data[i].buf_size << ")," - " expected " << test_data[i].expected - << ", ERROR: got " << buf; - ut_error; - } - } -} #endif /* !DBUG_OFF */ /** Match index columns between MySQL and InnoDB. @@ -5727,9 +5670,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; @@ -5794,46 +5737,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 @@ -6069,7 +6011,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 */ @@ -13351,6 +13293,49 @@ ha_innobase::discard_or_import_tablespace( DBUG_RETURN(0); } +/** Report a DROP TABLE failure due to a FOREIGN KEY constraint. +@param name table name +@param foreign constraint */ +ATTRIBUTE_COLD +static void delete_table_cannot_drop_foreign(const table_name_t &name, + const dict_foreign_t &foreign) +{ + mysql_mutex_lock(&dict_foreign_err_mutex); + rewind(dict_foreign_err_file); + ut_print_timestamp(dict_foreign_err_file); + fputs(" Cannot drop table ", dict_foreign_err_file); + ut_print_name(dict_foreign_err_file, nullptr, name.m_name); + fputs("\nbecause it is referenced by ", dict_foreign_err_file); + ut_print_name(dict_foreign_err_file, nullptr, foreign.foreign_table_name); + putc('\n', dict_foreign_err_file); + mysql_mutex_unlock(&dict_foreign_err_mutex); +} + +/** Check if DROP TABLE would fail due to a FOREIGN KEY constraint. +@param table table to be dropped +@param sqlcom thd_sql_command(current_thd) +@return whether child tables that refer to this table exist */ +static bool delete_table_check_foreigns(const dict_table_t &table, + enum_sql_command sqlcom) +{ + const bool drop_db{sqlcom == SQLCOM_DROP_DB}; + for (const auto foreign : table.referenced_set) + { + /* We should allow dropping a referenced table if creating + that referenced table has failed for some reason. For example + if referenced table is created but it column types that are + referenced do not match. */ + if (foreign->foreign_table == &table || + (drop_db && + dict_tables_have_same_db(table.name.m_name, + foreign->foreign_table_name_lookup))) + continue; + delete_table_cannot_drop_foreign(table.name, *foreign); + return true; + } + + return false; +} /** DROP TABLE (possibly as part of DROP DATABASE, CREATE/ALTER TABLE) @param name table name @@ -13365,8 +13350,8 @@ int ha_innobase::delete_table(const char *name) DBUG_EXECUTE_IF("test_normalize_table_name_low", test_normalize_table_name_low();); - DBUG_EXECUTE_IF("test_ut_format_name", test_ut_format_name();); + const enum_sql_command sqlcom= enum_sql_command(thd_sql_command(thd)); trx_t *parent_trx= check_trx_exists(thd); dict_table_t *table; @@ -13403,6 +13388,13 @@ int ha_innobase::delete_table(const char *name) DBUG_RETURN(0); } + if (parent_trx->check_foreigns && + delete_table_check_foreigns(*table, sqlcom)) + { + dict_sys.unlock(); + DBUG_RETURN(HA_ERR_ROW_IS_REFERENCED); + } + table->acquire(); dict_sys.unlock(); @@ -13435,14 +13427,7 @@ int ha_innobase::delete_table(const char *name) /* FOREIGN KEY constraints cannot exist on partitioned tables. */; #endif else - { - dict_sys.freeze(SRW_LOCK_CALL); - for (const dict_foreign_t* f : table->referenced_set) - if (dict_table_t* child= f->foreign_table) - if ((err= lock_table_for_trx(child, trx, LOCK_X)) != DB_SUCCESS) - break; - dict_sys.unfreeze(); - } + err= lock_table_children(table, trx); } dict_table_t *table_stats= nullptr, *index_stats= nullptr; @@ -13452,7 +13437,6 @@ int ha_innobase::delete_table(const char *name) const bool fts= err == DB_SUCCESS && (table->flags2 & (DICT_TF2_FTS_HAS_DOC_ID | DICT_TF2_FTS)); - const enum_sql_command sqlcom= enum_sql_command(thd_sql_command(thd)); if (fts) { @@ -13610,36 +13594,16 @@ err_exit: DBUG_RETURN(convert_error_code_to_mysql(err, 0, NULL)); } - if (!table->no_rollback() && trx->check_foreigns) + if (!table->no_rollback()) { - const bool drop_db= sqlcom == SQLCOM_DROP_DB; - for (auto foreign : table->referenced_set) + if (trx->check_foreigns && delete_table_check_foreigns(*table, sqlcom)) { - /* We should allow dropping a referenced table if creating - that referenced table has failed for some reason. For example - if referenced table is created but it column types that are - referenced do not match. */ - if (foreign->foreign_table == table || - (drop_db && - dict_tables_have_same_db(table->name.m_name, - foreign->foreign_table_name_lookup))) - continue; - mysql_mutex_lock(&dict_foreign_err_mutex); - rewind(dict_foreign_err_file); - ut_print_timestamp(dict_foreign_err_file); - fputs(" Cannot drop table ", dict_foreign_err_file); - ut_print_name(dict_foreign_err_file, trx, table->name.m_name); - fputs("\nbecause it is referenced by ", dict_foreign_err_file); - ut_print_name(dict_foreign_err_file, trx, foreign->foreign_table_name); - putc('\n', dict_foreign_err_file); - mysql_mutex_unlock(&dict_foreign_err_mutex); err= DB_CANNOT_DROP_CONSTRAINT; goto err_exit; } - } - if (!table->no_rollback()) err= trx->drop_table_foreign(table->name); + } if (err == DB_SUCCESS && table_stats && index_stats) err= trx->drop_table_statistics(table->name); @@ -13758,6 +13722,19 @@ int ha_innobase::truncate() update_thd(); +#ifdef UNIV_DEBUG + if (!thd_test_options(m_user_thd, OPTION_NO_FOREIGN_KEY_CHECKS)) + { + /* fk_truncate_illegal_if_parent() should have failed in + Sql_cmd_truncate_table::handler_truncate() if foreign_key_checks=ON + and child tables exist. */ + dict_sys.freeze(SRW_LOCK_CALL); + for (const auto foreign : m_prebuilt->table->referenced_set) + ut_ad(foreign->foreign_table == m_prebuilt->table); + dict_sys.unfreeze(); + } +#endif + if (is_read_only()) DBUG_RETURN(HA_ERR_TABLE_READONLY); @@ -13840,14 +13817,7 @@ int ha_innobase::truncate() dict_table_t *table_stats = nullptr, *index_stats = nullptr; MDL_ticket *mdl_table = nullptr, *mdl_index = nullptr; - dberr_t error= DB_SUCCESS; - - dict_sys.freeze(SRW_LOCK_CALL); - for (const dict_foreign_t *f : ib_table->referenced_set) - if (dict_table_t *child= f->foreign_table) - if ((error= lock_table_for_trx(child, trx, LOCK_X)) != DB_SUCCESS) - break; - dict_sys.unfreeze(); + dberr_t error= lock_table_children(ib_table, trx); if (error == DB_SUCCESS) error= lock_table_for_trx(ib_table, trx, LOCK_X); @@ -14038,16 +14008,7 @@ ha_innobase::rename_table( /* There is no need to lock any FOREIGN KEY child tables. */ } else if (dict_table_t *table = dict_table_open_on_name( norm_from, false, DICT_ERR_IGNORE_FK_NOKEY)) { - dict_sys.freeze(SRW_LOCK_CALL); - for (const dict_foreign_t* f : table->referenced_set) { - if (dict_table_t* child = f->foreign_table) { - error = lock_table_for_trx(child, trx, LOCK_X); - if (error != DB_SUCCESS) { - break; - } - } - } - dict_sys.unfreeze(); + error = lock_table_children(table, trx); if (error == DB_SUCCESS) { error = lock_table_for_trx(table, trx, LOCK_X); } @@ -15132,6 +15093,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()); @@ -15140,6 +15102,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 */ @@ -15343,6 +15326,35 @@ func_exit: 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 @@ -17513,6 +17525,7 @@ innodb_make_page_dirty(THD*, st_mysql_sys_var*, void*, const void* save) { mtr_t mtr; uint space_id = *static_cast(save); + srv_fil_make_page_dirty_debug= space_id; mysql_mutex_unlock(&LOCK_global_system_variables); fil_space_t* space = fil_space_t::get(space_id); @@ -18239,13 +18252,15 @@ buf_flush_list_now_set(THD*, st_mysql_sys_var*, void*, const void* save) return; const uint s= srv_fil_make_page_dirty_debug; mysql_mutex_unlock(&LOCK_global_system_variables); - if (s) - buf_flush_sync(); - else + if (s == 0 || srv_is_undo_tablespace(s)) { - while (buf_flush_list_space(fil_system.sys_space, nullptr)); + fil_space_t *space= fil_system.sys_space; + if (s) { space= fil_space_get(s); } + while (buf_flush_list_space(space, nullptr)); os_aio_wait_until_no_pending_writes(true); } + else + buf_flush_sync(); mysql_mutex_lock(&LOCK_global_system_variables); } @@ -18454,7 +18469,7 @@ static void innodb_log_file_size_update(THD *thd, st_mysql_sys_var*, const bool in_progress(buf_pool.get_oldest_modification(LSN_MAX) < log_sys.resize_in_progress()); if (in_progress) - my_cond_timedwait(&buf_pool.do_flush_list, + my_cond_timedwait(&buf_pool.done_flush_list, &buf_pool.flush_list_mutex.m_mutex, &abstime); mysql_mutex_unlock(&buf_pool.flush_list_mutex); if (!log_sys.resize_in_progress()) diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 60b56b4a22f..1b830e96793 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(); @@ -910,6 +911,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 2173e52d07b..d73e8f259bf 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 */ @@ -2748,6 +2743,9 @@ cannot_create_many_fulltext_index: online = false; } + static constexpr const char *not_implemented + = "Not implemented for system-versioned operations"; + if (ha_alter_info->handler_flags & ALTER_ADD_NON_UNIQUE_NON_PRIM_INDEX) { /* ADD FULLTEXT|SPATIAL INDEX requires a lock. @@ -2775,6 +2773,12 @@ cannot_create_many_fulltext_index: goto cannot_create_many_fulltext_index; } + if (altered_table->versioned()) { + ha_alter_info->unsupported_reason + = not_implemented; + DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); + } + add_fulltext = true; if (ha_alter_info->online && !ha_alter_info->unsupported_reason) { @@ -2813,10 +2817,8 @@ cannot_create_many_fulltext_index: // FIXME: implement Online DDL for system-versioned operations if (ha_alter_info->handler_flags & INNOBASE_ALTER_VERSIONED_REBUILD) { - if (ha_alter_info->online) { - ha_alter_info->unsupported_reason = - "Not implemented for system-versioned operations"; + ha_alter_info->unsupported_reason = not_implemented; } online = false; @@ -9865,13 +9867,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 @@ -11225,16 +11221,7 @@ ha_innobase::commit_inplace_alter_table( fts_optimize_remove_table(ctx->old_table); } - dict_sys.freeze(SRW_LOCK_CALL); - for (auto f : ctx->old_table->referenced_set) { - if (dict_table_t* child = f->foreign_table) { - error = lock_table_for_trx(child, trx, LOCK_X); - if (error != DB_SUCCESS) { - break; - } - } - } - dict_sys.unfreeze(); + error = lock_table_children(ctx->old_table, trx); if (ctx->new_table->fts) { ut_ad(!ctx->new_table->fts->add_wq); diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h index f46fae5bd2a..35a567d7bee 100644 --- a/storage/innobase/include/btr0btr.h +++ b/storage/innobase/include/btr0btr.h @@ -192,13 +192,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/dict0dict.h b/storage/innobase/include/dict0dict.h index 3513f21b5ec..47350f9c863 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -35,6 +35,7 @@ Created 1/8/1996 Heikki Tuuri #include #include +class MDL_context; class MDL_ticket; /** the first table or index ID for other than hard-coded system tables */ @@ -139,6 +140,21 @@ dict_acquire_mdl_shared(dict_table_t *table, MDL_ticket **mdl, dict_table_op_t table_op= DICT_TABLE_OP_NORMAL); +/** Acquire MDL shared for the table name. +@tparam trylock whether to use non-blocking operation +@param[in,out] table table object +@param[in,out] mdl_context MDL context +@param[out] mdl MDL ticket +@param[in] table_op operation to perform when opening +@return table object after locking MDL shared +@retval nullptr if the table is not readable, or if trylock && MDL blocked */ +template +__attribute__((nonnull, warn_unused_result)) +dict_table_t* +dict_acquire_mdl_shared(dict_table_t *table, + MDL_context *mdl_context, MDL_ticket **mdl, + dict_table_op_t table_op); + /** Look up a table by numeric identifier. @param[in] table_id table identifier @param[in] dict_locked data dictionary locked @@ -1312,13 +1328,7 @@ class dict_sys_t std::atomic latch_ex_wait_start; /** the rw-latch protecting the data dictionary cache */ - alignas(CPU_LEVEL1_DCACHE_LINESIZE) srw_lock latch; -#ifdef UNIV_DEBUG - /** whether latch is being held in exclusive mode (by any thread) */ - Atomic_relaxed latch_ex; - /** number of S-latch holders */ - Atomic_counter latch_readers; -#endif + alignas(CPU_LEVEL1_DCACHE_LINESIZE) IF_DBUG(srw_lock_debug,srw_lock) latch; public: /** Indexes of SYS_TABLE[] */ enum @@ -1469,15 +1479,12 @@ public: } #ifdef UNIV_DEBUG - /** @return whether any thread (not necessarily the current thread) - is holding the latch; that is, this check may return false - positives */ - bool frozen() const { return latch_readers || latch_ex; } - /** @return whether any thread (not necessarily the current thread) - is holding a shared latch */ - bool frozen_not_locked() const { return latch_readers; } + /** @return whether the current thread is holding the latch */ + bool frozen() const { return latch.have_any(); } + /** @return whether the current thread is holding a shared latch */ + bool frozen_not_locked() const { return latch.have_rd(); } /** @return whether the current thread holds the exclusive latch */ - bool locked() const { return latch_ex == pthread_self(); } + bool locked() const { return latch.have_wr(); } #endif private: /** Acquire the exclusive latch */ @@ -1492,13 +1499,7 @@ public: /** Exclusively lock the dictionary cache. */ void lock(SRW_LOCK_ARGS(const char *file, unsigned line)) { - if (latch.wr_lock_try()) - { - ut_ad(!latch_readers); - ut_ad(!latch_ex); - ut_d(latch_ex= pthread_self()); - } - else + if (!latch.wr_lock_try()) lock_wait(SRW_LOCK_ARGS(file, line)); } @@ -1511,27 +1512,11 @@ public: ATTRIBUTE_NOINLINE void unfreeze(); #else /** Unlock the data dictionary cache. */ - void unlock() - { - ut_ad(latch_ex == pthread_self()); - ut_ad(!latch_readers); - ut_d(latch_ex= 0); - latch.wr_unlock(); - } + void unlock() { latch.wr_unlock(); } /** Acquire a shared lock on the dictionary cache. */ - void freeze() - { - latch.rd_lock(); - ut_ad(!latch_ex); - ut_d(latch_readers++); - } + void freeze() { latch.rd_lock(); } /** Release a shared lock on the dictionary cache. */ - void unfreeze() - { - ut_ad(!latch_ex); - ut_ad(latch_readers--); - latch.rd_unlock(); - } + void unfreeze() { latch.rd_unlock(); } #endif /** Estimate the used memory occupied by the data dictionary diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 01365a1201d..6348d64ceca 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/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 128be0057b0..786999121c3 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -318,7 +318,6 @@ struct fil_space_t final ~fil_space_t() { ut_ad(!latch_owner); - ut_ad(!latch_count); latch.destroy(); } @@ -382,9 +381,9 @@ private: /** The reference count */ static constexpr uint32_t PENDING= ~(STOPPING | CLOSING | NEEDS_FSYNC); /** latch protecting all page allocation bitmap pages */ - srw_lock latch; + IF_DBUG(srw_lock_debug, srw_lock) latch; + /** the thread that holds the exclusive latch, or 0 */ pthread_t latch_owner; - ut_d(Atomic_relaxed latch_count;) public: /** MariaDB encryption data */ fil_space_crypt_t *crypt_data; @@ -977,40 +976,32 @@ public: bool recheck, bool encrypt); #ifdef UNIV_DEBUG - bool is_latched() const { return latch_count != 0; } + bool is_latched() const { return latch.have_any(); } #endif - bool is_owner() const { return latch_owner == pthread_self(); } + bool is_owner() const + { + const bool owner{latch_owner == pthread_self()}; + ut_ad(owner == latch.have_wr()); + return owner; + } /** Acquire the allocation latch in exclusive mode */ void x_lock() { latch.wr_lock(SRW_LOCK_CALL); ut_ad(!latch_owner); latch_owner= pthread_self(); - ut_ad(!latch_count.fetch_add(1)); } /** Release the allocation latch from exclusive mode */ void x_unlock() { - ut_ad(latch_count.fetch_sub(1) == 1); ut_ad(latch_owner == pthread_self()); latch_owner= 0; latch.wr_unlock(); } /** Acquire the allocation latch in shared mode */ - void s_lock() - { - ut_ad(!is_owner()); - latch.rd_lock(SRW_LOCK_CALL); - ut_ad(!latch_owner); - ut_d(latch_count.fetch_add(1)); - } + void s_lock() { latch.rd_lock(SRW_LOCK_CALL); } /** Release the allocation latch from shared mode */ - void s_unlock() - { - ut_ad(latch_count.fetch_sub(1)); - ut_ad(!latch_owner); - latch.rd_unlock(); - } + void s_unlock() { latch.rd_unlock(); } typedef span name_type; diff --git a/storage/innobase/include/fts0fts.h b/storage/innobase/include/fts0fts.h index c0151b44063..1d2b409be01 100644 --- a/storage/innobase/include/fts0fts.h +++ b/storage/innobase/include/fts0fts.h @@ -163,6 +163,9 @@ struct fts_token_t; struct fts_doc_ids_t; struct fts_index_cache_t; +/** Compare two DOC_ID. */ +int fts_doc_id_cmp(const void *p1, const void *p2) + __attribute__((nonnull, warn_unused_result)); /** Initialize the "fts_table" for internal query into FTS auxiliary tables */ @@ -412,6 +415,9 @@ inline void fts_doc_ids_free(fts_doc_ids_t* doc_ids) mem_heap_free(static_cast(doc_ids->self_heap->arg)); } +/** Sort an array of doc_id */ +void fts_doc_ids_sort(ib_vector_t *doc_ids); + /******************************************************************//** Notify the FTS system about an operation on an FTS-indexed table. */ void diff --git a/storage/innobase/include/fts0priv.h b/storage/innobase/include/fts0priv.h index ae0bb036e37..04faceb995e 100644 --- a/storage/innobase/include/fts0priv.h +++ b/storage/innobase/include/fts0priv.h @@ -271,27 +271,6 @@ fts_index_fetch_nodes( word, /*!< in: the word to fetch */ fts_fetch_t* fetch) /*!< in: fetch callback.*/ MY_ATTRIBUTE((nonnull)); -/******************************************************************//** -Compare two fts_trx_table_t instances, we actually compare the -table id's here. -@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ -UNIV_INLINE -int -fts_trx_table_cmp( -/*==============*/ - const void* v1, /*!< in: id1 */ - const void* v2) /*!< in: id2 */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); -/******************************************************************//** -Compare a table id with a trx_table_t table id. -@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ -UNIV_INLINE -int -fts_trx_table_id_cmp( -/*=================*/ - const void* p1, /*!< in: id1 */ - const void* p2) /*!< in: id2 */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); #define fts_sql_commit(trx) trx_commit_for_mysql(trx) #define fts_sql_rollback(trx) (trx)->rollback() /******************************************************************//** diff --git a/storage/innobase/include/fts0priv.inl b/storage/innobase/include/fts0priv.inl index 3cb09c924db..3d937bb3cd9 100644 --- a/storage/innobase/include/fts0priv.inl +++ b/storage/innobase/include/fts0priv.inl @@ -52,47 +52,3 @@ fts_read_object_id( if the id is HEX or DEC and do the right thing with it. */ return(sscanf(str, UINT64PFx, id) == 1); } - -/******************************************************************//** -Compare two fts_trx_table_t instances. -@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ -UNIV_INLINE -int -fts_trx_table_cmp( -/*==============*/ - const void* p1, /*!< in: id1 */ - const void* p2) /*!< in: id2 */ -{ - const dict_table_t* table1 - = (*static_cast(p1))->table; - - const dict_table_t* table2 - = (*static_cast(p2))->table; - - return((table1->id > table2->id) - ? 1 - : (table1->id == table2->id) - ? 0 - : -1); -} - -/******************************************************************//** -Compare a table id with a fts_trx_table_t table id. -@return < 0 if n1 < n2, 0 if n1 == n2,> 0 if n1 > n2 */ -UNIV_INLINE -int -fts_trx_table_id_cmp( -/*=================*/ - const void* p1, /*!< in: id1 */ - const void* p2) /*!< in: id2 */ -{ - const uintmax_t* table_id = static_cast(p1); - const dict_table_t* table2 - = (*static_cast(p2))->table; - - return((*table_id > table2->id) - ? 1 - : (*table_id == table2->id) - ? 0 - : -1); -} diff --git a/storage/innobase/include/fts0types.h b/storage/innobase/include/fts0types.h index fb278d543c4..7b95348bbc0 100644 --- a/storage/innobase/include/fts0types.h +++ b/storage/innobase/include/fts0types.h @@ -277,44 +277,6 @@ struct fts_token_t { /** It's defined in fts/fts0fts.c */ extern const fts_index_selector_t fts_index_selector[]; -/******************************************************************//** -Compare two fts_trx_row_t instances doc_ids. */ -UNIV_INLINE -int -fts_trx_row_doc_id_cmp( -/*===================*/ - /*!< out: - < 0 if n1 < n2, - 0 if n1 == n2, - > 0 if n1 > n2 */ - const void* p1, /*!< in: id1 */ - const void* p2); /*!< in: id2 */ - -/******************************************************************//** -Compare two fts_ranking_t instances doc_ids. */ -UNIV_INLINE -int -fts_ranking_doc_id_cmp( -/*===================*/ - /*!< out: - < 0 if n1 < n2, - 0 if n1 == n2, - > 0 if n1 > n2 */ - const void* p1, /*!< in: id1 */ - const void* p2); /*!< in: id2 */ - -/******************************************************************//** -Compare two doc_ids. */ -UNIV_INLINE -int fts_doc_id_cmp( -/*==================*/ - /*!< out: - < 0 if n1 < n2, - 0 if n1 == n2, - > 0 if n1 > n2 */ - const void* p1, /*!< in: id1 */ - const void* p2); /*!< in: id2 */ - /******************************************************************//** Duplicate a string. */ UNIV_INLINE diff --git a/storage/innobase/include/fts0types.inl b/storage/innobase/include/fts0types.inl index facc1e5c40b..5b57cad70d3 100644 --- a/storage/innobase/include/fts0types.inl +++ b/storage/innobase/include/fts0types.inl @@ -46,53 +46,6 @@ fts_string_dup( dst->f_n_char = src->f_n_char; } -/******************************************************************//** -Compare two fts_trx_row_t doc_ids. -@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ -UNIV_INLINE -int -fts_trx_row_doc_id_cmp( -/*===================*/ - const void* p1, /*!< in: id1 */ - const void* p2) /*!< in: id2 */ -{ - const fts_trx_row_t* tr1 = (const fts_trx_row_t*) p1; - const fts_trx_row_t* tr2 = (const fts_trx_row_t*) p2; - - return((int)(tr1->doc_id - tr2->doc_id)); -} - -/******************************************************************//** -Compare two fts_ranking_t doc_ids. -@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ -UNIV_INLINE -int -fts_ranking_doc_id_cmp( -/*===================*/ - const void* p1, /*!< in: id1 */ - const void* p2) /*!< in: id2 */ -{ - const fts_ranking_t* rk1 = (const fts_ranking_t*) p1; - const fts_ranking_t* rk2 = (const fts_ranking_t*) p2; - - return((int)(rk1->doc_id - rk2->doc_id)); -} - -/******************************************************************//** -Compare two doc_ids. -@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ -UNIV_INLINE -int fts_doc_id_cmp( -/*==================*/ - const void* p1, /*!< in: id1 */ - const void* p2) /*!< in: id2 */ -{ - const doc_id_t* up1 = static_cast(p1); - const doc_id_t* up2 = static_cast(p2); - - return static_cast(*up1 - *up2); -} - /******************************************************************//** Get the first character's code position for FTS index partition */ extern diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index 59ee7f551b4..08b9f4bcb35 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -438,6 +438,13 @@ dberr_t lock_table_for_trx(dict_table_t *table, trx_t *trx, lock_mode mode, bool no_wait= false) MY_ATTRIBUTE((nonnull, warn_unused_result)); +/** Lock the child tables of a table. +@param table parent table +@param trx transaction +@return error code */ +dberr_t lock_table_children(dict_table_t *table, trx_t *trx) + MY_ATTRIBUTE((nonnull, warn_unused_result)); + /** Exclusively lock the data dictionary tables. @param trx dictionary transaction @return error code @@ -724,13 +731,8 @@ private: bool m_initialised; /** mutex proteting the locks */ - alignas(CPU_LEVEL1_DCACHE_LINESIZE) srw_spin_lock latch; -#ifdef UNIV_DEBUG - /** The owner of exclusive latch (0 if none); protected by latch */ - std::atomic writer{0}; - /** Number of shared latches */ - std::atomic readers{0}; -#endif + alignas(CPU_LEVEL1_DCACHE_LINESIZE) + IF_DBUG(srw_lock_debug,srw_spin_lock) latch; #ifdef SUX_LOCK_GENERIC protected: /** mutex for hash_latch::wait() */ @@ -789,71 +791,35 @@ public: void wr_lock() { mysql_mutex_assert_not_owner(&wait_mutex); - ut_ad(!is_writer()); latch.wr_lock(); - ut_ad(!writer.exchange(pthread_self(), - std::memory_order_relaxed)); } /** Release exclusive lock_sys.latch */ - void wr_unlock() - { - ut_ad(writer.exchange(0, std::memory_order_relaxed) == - pthread_self()); - latch.wr_unlock(); - } + void wr_unlock() { latch.wr_unlock(); } /** Acquire shared lock_sys.latch */ void rd_lock() { mysql_mutex_assert_not_owner(&wait_mutex); - ut_ad(!is_writer()); latch.rd_lock(); - ut_ad(!writer.load(std::memory_order_relaxed)); - ut_d(readers.fetch_add(1, std::memory_order_relaxed)); } /** Release shared lock_sys.latch */ - void rd_unlock() - { - ut_ad(!is_writer()); - ut_ad(readers.fetch_sub(1, std::memory_order_relaxed)); - latch.rd_unlock(); - } + void rd_unlock() { latch.rd_unlock(); } #endif /** Try to acquire exclusive lock_sys.latch @return whether the latch was acquired */ - bool wr_lock_try() - { - ut_ad(!is_writer()); - if (!latch.wr_lock_try()) return false; - ut_ad(!writer.exchange(pthread_self(), - std::memory_order_relaxed)); - return true; - } + bool wr_lock_try() { return latch.wr_lock_try(); } /** Try to acquire shared lock_sys.latch @return whether the latch was acquired */ - bool rd_lock_try() - { - ut_ad(!is_writer()); - if (!latch.rd_lock_try()) return false; - ut_ad(!writer.load(std::memory_order_relaxed)); - ut_d(readers.fetch_add(1, std::memory_order_relaxed)); - return true; - } + bool rd_lock_try() { return latch.rd_lock_try(); } /** Assert that wr_lock() has been invoked by this thread */ - void assert_locked() const { ut_ad(is_writer()); } + void assert_locked() const { ut_ad(latch.have_wr()); } /** Assert that wr_lock() has not been invoked by this thread */ - void assert_unlocked() const { ut_ad(!is_writer()); } + void assert_unlocked() const { ut_ad(!latch.have_wr()); } #ifdef UNIV_DEBUG /** @return whether the current thread is the lock_sys.latch writer */ - bool is_writer() const - { -# ifdef SUX_LOCK_GENERIC - return writer.load(std::memory_order_relaxed) == pthread_self(); -# else - return writer.load(std::memory_order_relaxed) == pthread_self() || - (xtest() && !latch.is_locked_or_waiting()); -# endif - } + bool is_writer() const { return latch.have_wr(); } + /** @return whether the current thread is holding lock_sys.latch */ + bool is_holder() const { return latch.have_any(); } /** Assert that a lock shard is exclusively latched (by some thread) */ void assert_locked(const lock_t &lock) const; /** Assert that a table lock shard is exclusively latched by this thread */ @@ -965,14 +931,14 @@ extern lock_sys_t lock_sys; /** @return the index of an array element */ inline ulint lock_sys_t::hash_table::calc_hash(ulint fold) const { - ut_ad(lock_sys.is_writer() || lock_sys.readers); + ut_ad(lock_sys.is_holder()); return calc_hash(fold, n_cells); } /** Get a hash table cell. */ inline hash_cell_t *lock_sys_t::hash_table::cell_get(ulint fold) const { - ut_ad(lock_sys.is_writer() || lock_sys.readers); + ut_ad(lock_sys.is_holder()); return &array[calc_hash(fold)]; } diff --git a/storage/innobase/include/srw_lock.h b/storage/innobase/include/srw_lock.h index 01067322a0a..98c256d3b73 100644 --- a/storage/innobase/include/srw_lock.h +++ b/storage/innobase/include/srw_lock.h @@ -153,7 +153,7 @@ template class srw_lock_impl; /** Slim shared-update-exclusive lock with no recursion */ template -class ssux_lock_impl final +class ssux_lock_impl { #ifdef UNIV_PFS_RWLOCK friend class ssux_lock; @@ -550,3 +550,51 @@ typedef srw_lock_impl srw_lock; typedef srw_lock_impl srw_spin_lock; #endif + +#ifdef UNIV_DEBUG +# include + +class srw_lock_debug : private srw_lock +{ + /** The owner of the exclusive lock (0 if none) */ + std::atomic writer; + /** Protects readers */ + mutable srw_mutex readers_lock; + /** Threads that hold the lock in shared mode */ + std::atomic*> readers; + + /** Register a read lock. */ + void readers_register(); + +public: + void SRW_LOCK_INIT(mysql_pfs_key_t key); + void destroy(); + +#ifndef SUX_LOCK_GENERIC + /** @return whether any lock may be held by any thread */ + bool is_locked_or_waiting() const noexcept + { return srw_lock::is_locked_or_waiting(); } + /** @return whether an exclusive lock may be held by any thread */ + bool is_write_locked() const noexcept { return srw_lock::is_write_locked(); } +#endif + + /** Acquire an exclusive lock */ + void wr_lock(SRW_LOCK_ARGS(const char *file, unsigned line)); + /** @return whether an exclusive lock was acquired */ + bool wr_lock_try(); + /** Release after wr_lock() */ + void wr_unlock(); + /** Acquire a shared lock */ + void rd_lock(SRW_LOCK_ARGS(const char *file, unsigned line)); + /** @return whether a shared lock was acquired */ + bool rd_lock_try(); + /** Release after rd_lock() */ + void rd_unlock(); + /** @return whether this thread is between rd_lock() and rd_unlock() */ + bool have_rd() const noexcept; + /** @return whether this thread is between wr_lock() and wr_unlock() */ + bool have_wr() const noexcept; + /** @return whether this thread is holding rd_lock() or wr_lock() */ + bool have_any() const noexcept; +}; +#endif diff --git a/storage/innobase/include/trx0rseg.h b/storage/innobase/include/trx0rseg.h index 7fa43047b18..5df59863f32 100644 --- a/storage/innobase/include/trx0rseg.h +++ b/storage/innobase/include/trx0rseg.h @@ -59,7 +59,7 @@ struct alignas(CPU_LEVEL1_DCACHE_LINESIZE) trx_rseg_t /** tablespace containing the rollback segment; constant after init() */ fil_space_t *space; /** latch protecting everything except page_no, space */ - srw_spin_lock latch; + IF_DBUG(srw_lock_debug,srw_spin_lock) latch; /** rollback segment header page number; constant after init() */ uint32_t page_no; /** length of the TRX_RSEG_HISTORY list (number of transactions) */ diff --git a/storage/innobase/include/ut0ut.h b/storage/innobase/include/ut0ut.h index fe16ce149da..500b64552f9 100644 --- a/storage/innobase/include/ut0ut.h +++ b/storage/innobase/include/ut0ut.h @@ -242,20 +242,6 @@ ut_print_name( FILE* ef, /*!< in: stream */ const trx_t* trx, /*!< in: transaction */ const char* name); /*!< in: table name to print */ -/** Format a table name, quoted as an SQL identifier. -If the name contains a slash '/', the result will contain two -identifiers separated by a period (.), as in SQL -database_name.table_name. -@see table_name_t -@param[in] name table or index name -@param[out] formatted formatted result, will be NUL-terminated -@param[in] formatted_size size of the buffer in bytes -@return pointer to 'formatted' */ -char* -ut_format_name( - const char* name, - char* formatted, - ulint formatted_size); /**********************************************************************//** Catenate files. */ diff --git a/storage/innobase/include/ut0vec.h b/storage/innobase/include/ut0vec.h index f4660f9646c..ad43e1c8d7d 100644 --- a/storage/innobase/include/ut0vec.h +++ b/storage/innobase/include/ut0vec.h @@ -200,15 +200,6 @@ ib_vector_last_const( /* out: pointer to last element */ const ib_vector_t* vec); /* in: vector */ -/******************************************************************** -Sort the vector elements. */ -UNIV_INLINE -void -ib_vector_sort( -/*===========*/ - ib_vector_t* vec, /* in/out: vector */ - ib_compare_t compare); /* in: the comparator to use for sort */ - /******************************************************************** The default ib_vector_t heap free. Does nothing. */ UNIV_INLINE diff --git a/storage/innobase/include/ut0vec.inl b/storage/innobase/include/ut0vec.inl index 531f0f22ae0..1a844dd835d 100644 --- a/storage/innobase/include/ut0vec.inl +++ b/storage/innobase/include/ut0vec.inl @@ -304,19 +304,6 @@ ib_vector_remove( return((old_used_count != vec->used) ? current : NULL); } -/******************************************************************** -Sort the vector elements. */ -UNIV_INLINE -void -ib_vector_sort( -/*===========*/ - /* out: void */ - ib_vector_t* vec, /* in: vector */ - ib_compare_t compare)/* in: the comparator to use for sort */ -{ - qsort(vec->data, vec->used, vec->sizeof_value, compare); -} - /******************************************************************** Destroy the vector. Make sure the vector owns the allocator, e.g., the heap in the the heap allocator. */ diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index df51ceb16d8..907eaf58997 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -47,6 +47,7 @@ Created 5/7/1996 Heikki Tuuri #include "que0que.h" #include "scope.h" #include +#include #include @@ -173,7 +174,7 @@ void lock_sys_t::assert_locked(const dict_table_t &table) const ut_ad(!table.is_temporary()); if (is_writer()) return; - ut_ad(readers); + ut_ad(latch.have_rd()); ut_ad(table.lock_mutex_is_owner()); } @@ -182,7 +183,7 @@ void lock_sys_t::hash_table::assert_locked(const page_id_t id) const { if (lock_sys.is_writer()) return; - ut_ad(lock_sys.readers); + ut_ad(lock_sys.is_holder()); ut_ad(latch(cell_get(id.fold()))->is_locked()); } @@ -191,7 +192,7 @@ void lock_sys_t::assert_locked(const hash_cell_t &cell) const { if (is_writer()) return; - ut_ad(lock_sys.readers); + ut_ad(lock_sys.is_holder()); ut_ad(hash_table::latch(const_cast(&cell))->is_locked()); } #endif @@ -426,13 +427,10 @@ void lock_sys_t::wr_lock(const char *file, unsigned line) { mysql_mutex_assert_not_owner(&wait_mutex); latch.wr_lock(file, line); - ut_ad(!writer.exchange(pthread_self(), std::memory_order_relaxed)); } /** Release exclusive lock_sys.latch */ void lock_sys_t::wr_unlock() { - ut_ad(writer.exchange(0, std::memory_order_relaxed) == - pthread_self()); latch.wr_unlock(); } @@ -441,15 +439,11 @@ void lock_sys_t::rd_lock(const char *file, unsigned line) { mysql_mutex_assert_not_owner(&wait_mutex); latch.rd_lock(file, line); - ut_ad(!writer.load(std::memory_order_relaxed)); - ut_d(readers.fetch_add(1, std::memory_order_relaxed)); } /** Release shared lock_sys.latch */ void lock_sys_t::rd_unlock() { - ut_ad(!writer.load(std::memory_order_relaxed)); - ut_ad(readers.fetch_sub(1, std::memory_order_relaxed)); latch.rd_unlock(); } #endif @@ -3940,6 +3934,8 @@ static void lock_table_dequeue(lock_t *in_lock, bool owns_wait_mutex) dberr_t lock_table_for_trx(dict_table_t *table, trx_t *trx, lock_mode mode, bool no_wait) { + ut_ad(!dict_sys.frozen()); + mem_heap_t *heap= mem_heap_create(512); sel_node_t *node= sel_node_create(heap); que_thr_t *thr= pars_complete_graph_for_exec(node, trx, heap, nullptr); @@ -3976,6 +3972,67 @@ run_again: return err; } +/** Lock the child tables of a table. +@param table parent table +@param trx transaction +@return error code */ +dberr_t lock_table_children(dict_table_t *table, trx_t *trx) +{ + MDL_context *mdl_context= + static_cast(thd_mdl_context(trx->mysql_thd)); + ut_ad(mdl_context); + struct table_mdl{dict_table_t* table; MDL_ticket *mdl;}; + std::vector children; + children.emplace_back(table_mdl{table, nullptr}); + + dberr_t err= DB_SUCCESS; + dict_sys.freeze(SRW_LOCK_CALL); + + rescan: + for (auto f : table->referenced_set) + if (dict_table_t *child= f->foreign_table) + { + if (std::find_if(children.begin(), children.end(), + [&](const table_mdl &c){ return c.table == child; }) != + children.end()) + continue; /* We already acquired MDL on this child table. */ + MDL_ticket *mdl= nullptr; + child->acquire(); + child= dict_acquire_mdl_shared(child, mdl_context, &mdl, + DICT_TABLE_OP_NORMAL); + if (child) + { + if (!mdl) + child->release(); + children.emplace_back(table_mdl{child, mdl}); + goto rescan; + } + err= DB_LOCK_WAIT_TIMEOUT; + break; + } + dict_sys.unfreeze(); + + if (err == DB_SUCCESS) + for (const table_mdl &child : children) + if (child.mdl) + if ((err= lock_table_for_trx(child.table, trx, LOCK_X)) != DB_SUCCESS) + break; + + dict_sys.freeze(SRW_LOCK_CALL); + for (table_mdl &child : children) + { + if (child.mdl) + { + child.table->release(); + mdl_context->release_lock(child.mdl); + } + } + dict_sys.unfreeze(); + + return err; +} + + /** Exclusively lock the data dictionary tables. @param trx dictionary transaction @return error code diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index ddb7f2318c3..6f7fb6df906 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -175,7 +175,9 @@ void log_file_t::write(os_offset_t offset, span buf) noexcept ut_ad(is_opened()); if (dberr_t err= os_file_write_func(IORequestWrite, "ib_logfile0", m_file, buf.data(), offset, buf.size())) - ib::fatal() << "write(\"ib_logfile0\") returned " << err; + ib::fatal() << "write(\"ib_logfile0\") returned " << err + << ". Operating system error number " + << IF_WIN(GetLastError(), errno) << "."; } #ifdef HAVE_PMEM diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 7f08c7e6313..13dbb4c01df 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -4037,9 +4037,10 @@ static bool recv_scan_log(bool last_phase) const lsn_t end{recv_sys.file_checkpoint}; ut_ad(!end || end == recv_sys.lsn); + bool corrupt_fs= recv_sys.is_corrupt_fs(); mysql_mutex_unlock(&recv_sys.mutex); - if (!end) + if (!end && !corrupt_fs) { recv_sys.set_corrupt_log(); sql_print_error("InnoDB: Missing FILE_CHECKPOINT(" LSN_PF @@ -4519,6 +4520,9 @@ read_only_recovery: LSN_PF, recv_sys.lsn); goto err_exit; } + if (recv_sys.is_corrupt_fs()) { + goto err_exit; + } ut_ad(recv_sys.file_checkpoint); if (rewind) { recv_sys.lsn = log_sys.next_checkpoint_lsn; @@ -4557,9 +4561,9 @@ read_only_recovery: do { rescan = recv_scan_log(false); - ut_ad(!recv_sys.is_corrupt_fs()); - if (recv_sys.is_corrupt_log()) { + if (recv_sys.is_corrupt_log() || + recv_sys.is_corrupt_fs()) { goto err_exit; } diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index d83fd70855b..dc0b073618e 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -233,7 +233,14 @@ static void insert_imported(buf_block_t *block) if (block->page.oldest_modification() <= 1) { log_sys.latch.rd_lock(SRW_LOCK_CALL); - const lsn_t lsn= log_sys.last_checkpoint_lsn; + /* For unlogged mtrs (MTR_LOG_NO_REDO), we use the current system LSN. The + mtr that generated the LSN is either already committed or in mtr_t::commit. + Shared latch and relaxed atomics should be fine here as it is guaranteed + that both the current mtr and the mtr that generated the LSN would have + added the dirty pages to flush list before we access the minimum LSN during + checkpoint. log_checkpoint_low() acquires exclusive log_sys.latch before + commencing. */ + const lsn_t lsn= log_sys.get_lsn(); mysql_mutex_lock(&buf_pool.flush_list_mutex); buf_pool.insert_into_flush_list (buf_pool.prepare_insert_into_flush_list(lsn), block, lsn); @@ -511,10 +518,8 @@ void mtr_t::rollback_to_savepoint(ulint begin, ulint end) /** Set create_lsn. */ inline void fil_space_t::set_create_lsn(lsn_t lsn) { -#ifndef SUX_LOCK_GENERIC /* Concurrent log_checkpoint_low() must be impossible. */ - ut_ad(latch.is_write_locked()); -#endif + ut_ad(latch.have_wr()); create_lsn= lsn; } diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index c786583118e..e1d61776643 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -45,6 +45,8 @@ Created 2012-02-08 by Sunny Bains. #include "lzo/lzo1x.h" #include "snappy-c.h" #include "log.h" +#include "table.h" +#include "ha_innodb.h" #include "scope.h" @@ -4225,6 +4227,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. @@ -4251,6 +4284,23 @@ row_import_for_mysql( ut_ad(trx->state == TRX_STATE_ACTIVE); ut_ad(!table->is_readable()); +#ifdef BTR_CUR_HASH_ADAPT + /* On DISCARD TABLESPACE, we did not drop any adaptive hash + index entries. If we replaced the discarded tablespace with a + smaller one here, there could still be some adaptive hash + index entries that point to cached garbage pages in the buffer + pool, because PageConverter::operator() only evicted those + pages that were replaced by the imported pages. We must + detach any remaining adaptive hash index entries, because the + adaptive hash index must be a subset of the table contents; + false positives are not tolerated. */ + for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); index; + index = UT_LIST_GET_NEXT(indexes, index)) { + index = index->clone_if_needed(); + } +#endif /* BTR_CUR_HASH_ADAPT */ + UT_LIST_GET_FIRST(table->indexes)->clear_instant_alter(); + /* Assign an undo segment for the transaction, so that the transaction will be recovered after a crash. */ @@ -4370,21 +4420,6 @@ row_import_for_mysql( DBUG_EXECUTE_IF("ib_import_reset_space_and_lsn_failure", err = DB_TOO_MANY_CONCURRENT_TRXS;); -#ifdef BTR_CUR_HASH_ADAPT - /* On DISCARD TABLESPACE, we did not drop any adaptive hash - index entries. If we replaced the discarded tablespace with a - smaller one here, there could still be some adaptive hash - index entries that point to cached garbage pages in the buffer - pool, because PageConverter::operator() only evicted those - pages that were replaced by the imported pages. We must - detach any remaining adaptive hash index entries, because the - adaptive hash index must be a subset of the table contents; - false positives are not tolerated. */ - for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); index; - index = UT_LIST_GET_NEXT(indexes, index)) { - index = index->clone_if_needed(); - } -#endif /* BTR_CUR_HASH_ADAPT */ if (err != DB_SUCCESS) { char table_name[MAX_FULL_NAME_LEN + 1]; @@ -4547,14 +4582,8 @@ row_import_for_mysql( table->flags2 &= ~DICT_TF2_DISCARDED & ((1U << DICT_TF2_BITS) - 1); /* Set autoinc value read from .cfg file, if one was specified. - Otherwise, keep the PAGE_ROOT_AUTO_INC as is. */ - if (autoinc) { - ib::info() << table->name << " autoinc value set to " - << autoinc; - - table->autoinc = autoinc--; - btr_write_autoinc(dict_table_get_first_index(table), autoinc); - } + Otherwise, read the PAGE_ROOT_AUTO_INC and set it to table autoinc. */ + row_import_autoinc(table, prebuilt, autoinc); return row_import_cleanup(prebuilt, err); } diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index f95e97fb6b5..fc622cd77a5 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -528,8 +528,6 @@ static ulint row_merge_bulk_buf_add(row_merge_buf_t* buf, @param[in,out] row table row @param[in] ext cache of externally stored column prefixes, or NULL -@param[in] history_fts row is historical in a system-versioned table - on which a FTS_DOC_ID_INDEX(FTS_DOC_ID) exists @param[in,out] doc_id Doc ID if we are creating FTS index @param[in,out] conv_heap memory heap where to allocate data when @@ -552,7 +550,6 @@ row_merge_buf_add( fts_psort_t* psort_info, dtuple_t* row, const row_ext_t* ext, - const bool history_fts, doc_id_t* doc_id, mem_heap_t* conv_heap, dberr_t* err, @@ -617,7 +614,7 @@ error: : NULL; /* Process the Doc ID column */ - if (!v_col && (history_fts || *doc_id) + if (!v_col && *doc_id && col->ind == index->table->fts->doc_col) { fts_write_doc_id((byte*) &write_doc_id, *doc_id); @@ -678,7 +675,7 @@ error: } /* Tokenize and process data for FTS */ - if (!history_fts && (index->type & DICT_FTS)) { + if (index->type & DICT_FTS) { fts_doc_item_t* doc_item; byte* value; void* ptr; @@ -1897,6 +1894,7 @@ row_merge_read_clustered_index( DBUG_ENTER("row_merge_read_clustered_index"); ut_ad((old_table == new_table) == !col_map); + ut_ad(old_table->fts || !new_table->fts || !new_table->versioned()); ut_ad(!defaults || col_map); ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE)); ut_ad(trx->id); @@ -2122,7 +2120,6 @@ corrupted_metadata: dtuple_t* row; row_ext_t* ext; page_cur_t* cur = btr_pcur_get_page_cur(&pcur); - bool history_row, history_fts = false; stage->n_pk_recs_inc(); @@ -2384,11 +2381,6 @@ end_of_index: row_heap); ut_ad(row); - history_row = new_table->versioned() - && dtuple_get_nth_field(row, new_table->vers_end) - ->vers_history_row(); - history_fts = history_row && new_table->fts; - for (ulint i = 0; i < n_nonnull; i++) { dfield_t* field = &row->fields[nonnull[i]]; @@ -2417,7 +2409,7 @@ end_of_index: } /* Get the next Doc ID */ - if (add_doc_id && !history_fts) { + if (add_doc_id) { doc_id++; } else { doc_id = 0; @@ -2457,7 +2449,9 @@ end_of_index: add_autoinc); if (new_table->versioned()) { - if (history_row) { + if (dtuple_get_nth_field(row, + new_table->vers_end) + ->vers_history_row()) { if (dfield_get_type(dfield)->prtype & DATA_NOT_NULL) { err = DB_UNSUPPORTED; my_error(ER_UNSUPPORTED_EXTENSION, MYF(0), @@ -2573,7 +2567,7 @@ write_buffers: if (UNIV_LIKELY (row && (rows_added = row_merge_buf_add( buf, fts_index, old_table, new_table, - psort_info, row, ext, history_fts, + psort_info, row, ext, &doc_id, conv_heap, &err, &v_heap, eval_table, trx, col_collate)))) { @@ -2906,7 +2900,7 @@ write_buffers: (!(rows_added = row_merge_buf_add( buf, fts_index, old_table, new_table, psort_info, - row, ext, history_fts, &doc_id, + row, ext, &doc_id, conv_heap, &err, &v_heap, eval_table, trx, col_collate)))) { /* An empty buffer should have enough diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 3de22a2ede4..2bffcddaee0 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -2377,7 +2377,6 @@ row_discard_tablespace( dict_table_change_id_in_cache(table, new_id); dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); - if (index) index->clear_instant_alter(); /* Reset the root page numbers. */ for (; index; index = UT_LIST_GET_NEXT(indexes, index)) { diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index b5dd0e380df..916a5dde15c 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -4458,13 +4458,11 @@ early_not_found: DBUG_RETURN(DB_RECORD_NOT_FOUND); } +#if SIZEOF_SIZE_T < 8 + if (UNIV_LIKELY(~prebuilt->n_rows_fetched)) +#endif prebuilt->n_rows_fetched++; - if (prebuilt->n_rows_fetched > 1000000000) { - /* Prevent wrap-over */ - prebuilt->n_rows_fetched = 500000000; - } - mode = pcur->search_mode; } diff --git a/storage/innobase/sync/srw_lock.cc b/storage/innobase/sync/srw_lock.cc index 5afb79f24ff..27fc7e2d2bb 100644 --- a/storage/innobase/sync/srw_lock.cc +++ b/storage/innobase/sync/srw_lock.cc @@ -548,3 +548,120 @@ template void ssux_lock_impl::rd_unlock(); template void ssux_lock_impl::u_unlock(); template void ssux_lock_impl::wr_unlock(); #endif /* UNIV_PFS_RWLOCK */ + +#ifdef UNIV_DEBUG +void srw_lock_debug::SRW_LOCK_INIT(mysql_pfs_key_t key) +{ + srw_lock::SRW_LOCK_INIT(key); + readers_lock.init(); + ut_ad(!readers.load(std::memory_order_relaxed)); + ut_ad(!have_any()); +} + +void srw_lock_debug::destroy() +{ + ut_ad(!writer); + if (auto r= readers.load(std::memory_order_relaxed)) + { + readers.store(0, std::memory_order_relaxed); + ut_ad(r->empty()); + delete r; + } + srw_lock::destroy(); +} + +bool srw_lock_debug::wr_lock_try() +{ + ut_ad(!have_any()); + if (!srw_lock::wr_lock_try()) + return false; + ut_ad(!writer); + writer.store(pthread_self(), std::memory_order_relaxed); + return true; +} + +void srw_lock_debug::wr_lock(SRW_LOCK_ARGS(const char *file, unsigned line)) +{ + ut_ad(!have_any()); + srw_lock::wr_lock(SRW_LOCK_ARGS(file, line)); + ut_ad(!writer); + writer.store(pthread_self(), std::memory_order_relaxed); +} + +void srw_lock_debug::wr_unlock() +{ + ut_ad(have_wr()); + writer.store(0, std::memory_order_relaxed); + srw_lock::wr_unlock(); +} + +void srw_lock_debug::readers_register() +{ + readers_lock.wr_lock(); + auto r= readers.load(std::memory_order_relaxed); + if (!r) + { + r= new std::unordered_multiset(); + readers.store(r, std::memory_order_relaxed); + } + r->emplace(pthread_self()); + readers_lock.wr_unlock(); +} + +bool srw_lock_debug::rd_lock_try() +{ + ut_ad(!have_any()); + if (!srw_lock::rd_lock_try()) + return false; + readers_register(); + return true; +} + +void srw_lock_debug::rd_lock(SRW_LOCK_ARGS(const char *file, unsigned line)) +{ + ut_ad(!have_any()); + srw_lock::rd_lock(SRW_LOCK_ARGS(file, line)); + readers_register(); +} + +void srw_lock_debug::rd_unlock() +{ + const pthread_t self= pthread_self(); + ut_ad(writer != self); + readers_lock.wr_lock(); + auto r= readers.load(std::memory_order_relaxed); + ut_ad(r); + auto i= r->find(self); + ut_ad(i != r->end()); + r->erase(i); + readers_lock.wr_unlock(); + + srw_lock::rd_unlock(); +} + +bool srw_lock_debug::have_rd() const noexcept +{ + if (auto r= readers.load(std::memory_order_relaxed)) + { + readers_lock.wr_lock(); + bool found= r->find(pthread_self()) != r->end(); + readers_lock.wr_unlock(); + ut_ad(!found || is_locked()); + return found; + } + return false; +} + +bool srw_lock_debug::have_wr() const noexcept +{ + if (writer != pthread_self()) + return false; + ut_ad(is_write_locked()); + return true; +} + +bool srw_lock_debug::have_any() const noexcept +{ + return have_wr() || have_rd(); +} +#endif diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 9a295e0b2c1..b8a05dc36eb 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -393,9 +393,7 @@ static void trx_purge_free_segment(buf_block_t *rseg_hdr, buf_block_t *block, void purge_sys_t::rseg_enable(trx_rseg_t &rseg) { ut_ad(this == &purge_sys); -#ifndef SUX_LOCK_GENERIC - ut_ad(rseg.latch.is_write_locked()); -#endif + ut_ad(rseg.latch.have_wr()); uint8_t skipped= skipped_rseg; ut_ad(skipped < TRX_SYS_N_RSEGS); if (&rseg == &trx_sys.rseg_array[skipped]) @@ -871,9 +869,7 @@ void purge_sys_t::rseg_get_next_history_log() { fil_addr_t prev_log_addr; -#ifndef SUX_LOCK_GENERIC - ut_ad(rseg->latch.is_write_locked()); -#endif + ut_ad(rseg->latch.have_wr()); ut_a(rseg->last_page_no != FIL_NULL); tail.trx_no= rseg->last_trx_no() + 1; @@ -988,9 +984,7 @@ inline trx_purge_rec_t purge_sys_t::get_next_rec(roll_ptr_t roll_ptr) { ut_ad(next_stored); ut_ad(tail.trx_no < low_limit_no()); -#ifndef SUX_LOCK_GENERIC - ut_ad(rseg->latch.is_write_locked()); -#endif + ut_ad(rseg->latch.have_wr()); if (!offset) { diff --git a/storage/innobase/unittest/CMakeLists.txt b/storage/innobase/unittest/CMakeLists.txt index 7dd7c111baa..9330d231f06 100644 --- a/storage/innobase/unittest/CMakeLists.txt +++ b/storage/innobase/unittest/CMakeLists.txt @@ -17,6 +17,10 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/unittest/mytap ${CMAKE_SOURCE_DIR}/storage/innobase/include ${CMAKE_SOURCE_DIR}/tpool) +ADD_EXECUTABLE(innodb_rbt-t innodb_rbt-t.cc ../ut/ut0rbt.cc) +TARGET_LINK_LIBRARIES(innodb_rbt-t mysys mytap) +ADD_DEPENDENCIES(innodb_rbt-t GenError) +MY_ADD_TEST(innodb_rbt) ADD_EXECUTABLE(innodb_fts-t innodb_fts-t.cc) TARGET_LINK_LIBRARIES(innodb_fts-t mysys mytap) ADD_DEPENDENCIES(innodb_fts-t GenError) diff --git a/storage/innobase/unittest/innodb_rbt-t.cc b/storage/innobase/unittest/innodb_rbt-t.cc new file mode 100644 index 00000000000..38b980da7d9 --- /dev/null +++ b/storage/innobase/unittest/innodb_rbt-t.cc @@ -0,0 +1,83 @@ +#include "tap.h" +#include "ut0rbt.h" +#include "ut0new.h" + +const size_t alloc_max_retries= 0; +void os_thread_sleep(ulint) { abort(); } +void ut_dbg_assertion_failed(const char *, const char *, unsigned) +{ abort(); } +namespace ib { fatal_or_error::~fatal_or_error() { abort(); } } +#ifdef UNIV_PFS_MEMORY +PSI_memory_key mem_key_other, mem_key_std; +PSI_memory_key ut_new_get_key_by_file(uint32_t) { return mem_key_std; } +#endif + +static const uint64_t doc_ids[]= +{ + 103571, 104018, 106821, 108647, 109352, 109379, + 110325, 122868, 210682130, 231275441, 234172769, 366236849, + 526467159, 1675241735, 1675243405, 1947751899, 1949940363, 2033691953, + 2148227299, 2256289791, 2294223591, 2367501260, 2792700091, 2792701220, + 2817121627, 2820680352, 2821165664, 3253312130, 3404918378, 3532599429, + 3538712078, 3539373037, 3546479309, 3566641838, 3580209634, 3580871267, + 3693930556, 3693932734, 3693932983, 3781949558, 3839877411, 3930968983 +}; + +static int fts_doc_id_cmp(const void *p1, const void *p2) +{ + uint64_t a= *static_cast(p1), + b= *static_cast(p2); + return b > a ? -1 : a > b; +} + + +static int fts_doc_id_buggy_cmp(const void *p1, const void *p2) +{ + return int(*static_cast(p1) - + *static_cast(p2)); +} + +typedef int (*comparator) (const void*, const void*); + +static void rbt_populate(ib_rbt_t *rbt) +{ + ib_rbt_bound_t parent; + for (const uint64_t &doc_id : doc_ids) + { + if (rbt_search(rbt, &parent, &doc_id)) + rbt_add_node(rbt, &parent, &doc_id); + } +} + +static void rbt_populate2(ib_rbt_t *rbt) +{ + for (const uint64_t &doc_id : doc_ids) + rbt_insert(rbt, &doc_id, &doc_id); +} + +static bool rbt_search_all(ib_rbt_t *rbt) +{ + ib_rbt_bound_t parent; + for (const uint64_t &doc_id : doc_ids) + if (rbt_search(rbt, &parent, &doc_id)) + return false; + return true; +} + +static void rbt_test(comparator cmp, bool buggy) +{ + ib_rbt_t *rbt= rbt_create(sizeof(uint64_t), cmp); + rbt_populate(rbt); + ok(rbt_search_all(rbt) != buggy, "search after populate"); + rbt_free(rbt); + rbt= rbt_create(sizeof(uint64_t), cmp); + rbt_populate2(rbt); + ok(rbt_search_all(rbt) != buggy, "search after populate2"); + rbt_free(rbt); +} + +int main () +{ + rbt_test(fts_doc_id_buggy_cmp, true); + rbt_test(fts_doc_id_cmp, false); +} diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc index 7b69042c0a5..cdcec63ef2a 100644 --- a/storage/innobase/ut/ut0ut.cc +++ b/storage/innobase/ut/ut0ut.cc @@ -258,47 +258,6 @@ ut_print_name( } } -/** Format a table name, quoted as an SQL identifier. -If the name contains a slash '/', the result will contain two -identifiers separated by a period (.), as in SQL -database_name.table_name. -@see table_name_t -@param[in] name table or index name -@param[out] formatted formatted result, will be NUL-terminated -@param[in] formatted_size size of the buffer in bytes -@return pointer to 'formatted' */ -char* -ut_format_name( - const char* name, - char* formatted, - ulint formatted_size) -{ - switch (formatted_size) { - case 1: - formatted[0] = '\0'; - /* FALL-THROUGH */ - case 0: - return(formatted); - } - - char* end; - - end = innobase_convert_name(formatted, formatted_size, - name, strlen(name), NULL); - - /* If the space in 'formatted' was completely used, then sacrifice - the last character in order to write '\0' at the end. */ - if ((ulint) (end - formatted) == formatted_size) { - end--; - } - - ut_a((ulint) (end - formatted) < formatted_size); - - *end = '\0'; - - return(formatted); -} - /**********************************************************************//** Catenate files. */ void diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index a1be0ed1499..991bc73f3b8 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 */ diff --git a/storage/rocksdb/mysql-test/rocksdb/r/partition.result b/storage/rocksdb/mysql-test/rocksdb/r/partition.result index a7f2a6112c1..1ba966e9e07 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/partition.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/partition.result @@ -46,7 +46,6 @@ CREATE TABLE t1 (i INT, j INT, k INT, PRIMARY KEY (i)) ENGINE = ROCKSDB PARTITIO Table Op Msg_type Msg_text test.t1 optimize status OK Table Op Msg_type Msg_text -test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK Table Op Msg_type Msg_text test.t1 repair status OK diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_33242.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_33242.result new file mode 100644 index 00000000000..bbbc4499af4 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_33242.result @@ -0,0 +1,4 @@ +set @old_old_mode=@@global.old_mode; +set global old_mode=4; +INSTALL SONAME 'ha_spider.so'; +set global old_mode=@old_old_mode; diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_33441.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_33441.result new file mode 100644 index 00000000000..b19194f13b5 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_33441.result @@ -0,0 +1,7 @@ +# +# MDEV-33441 No spider variables available is Spider is loaded upon server startup +# +set spider_same_server_link=0; +# +# end of test mdev_33441 +# diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_33441_fail.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_33441_fail.result new file mode 100644 index 00000000000..e6123ed429b --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_33441_fail.result @@ -0,0 +1,10 @@ +# +# MDEV-33441 No spider variables available is Spider is loaded upon server startup +# +select * from mysql.plugin; +name dl +show variables like 'spider%'; +Variable_name Value +# +# end of test mdev_33441_fail +# diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_33242.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_33242.test new file mode 100644 index 00000000000..215dab25f09 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_33242.test @@ -0,0 +1,6 @@ +set @old_old_mode=@@global.old_mode; +set global old_mode=4; +INSTALL SONAME 'ha_spider.so'; +set global old_mode=@old_old_mode; +--disable_query_log +--source ../../include/clean_up_spider.inc diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_33441.opt b/storage/spider/mysql-test/spider/bugfix/t/mdev_33441.opt new file mode 100644 index 00000000000..924ea4e31ef --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_33441.opt @@ -0,0 +1 @@ +--plugin-load-add=ha_spider diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_33441.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_33441.test new file mode 100644 index 00000000000..a2e0ddafe01 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_33441.test @@ -0,0 +1,10 @@ +--echo # +--echo # MDEV-33441 No spider variables available is Spider is loaded upon server startup +--echo # + +# We test that at least one spider variable exists. +set spider_same_server_link=0; + +--echo # +--echo # end of test mdev_33441 +--echo # diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_33441_fail.opt b/storage/spider/mysql-test/spider/bugfix/t/mdev_33441_fail.opt new file mode 100644 index 00000000000..28f1ce4825b --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_33441_fail.opt @@ -0,0 +1,2 @@ +--plugin-load-add=ha_spider +--debug-dbug=d,fail_spider_init_retry diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_33441_fail.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_33441_fail.test new file mode 100644 index 00000000000..6734b477583 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_33441_fail.test @@ -0,0 +1,10 @@ +--source include/have_debug.inc +--echo # +--echo # MDEV-33441 No spider variables available is Spider is loaded upon server startup +--echo # +# We test that when retry fails, spider variables are deleted. +select * from mysql.plugin; +show variables like 'spider%'; +--echo # +--echo # end of test mdev_33441_fail +--echo # diff --git a/storage/spider/mysql-test/spider/bugfix/t/self_reference_multi.test b/storage/spider/mysql-test/spider/bugfix/t/self_reference_multi.test index 4263560baa1..de75f0eec3f 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/self_reference_multi.test +++ b/storage/spider/mysql-test/spider/bugfix/t/self_reference_multi.test @@ -19,8 +19,10 @@ eval create table t0 (c int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "$srv", eval alter table t2 ENGINE=Spider COMMENT='WRAPPER "mysql", srv "$srv",TABLE "t0"'; --error 12719 select * from t0; +--replace_result test.t1 test.t0 test.t2 test.t0 --error 12719 select * from t1; +--replace_result test.t1 test.t0 test.t2 test.t0 --error 12719 select * from t2; drop table t0, t1, t2; diff --git a/storage/spider/spd_init_query.h b/storage/spider/spd_init_query.h index 35a250c7d3c..2400046c261 100644 --- a/storage/spider/spd_init_query.h +++ b/storage/spider/spd_init_query.h @@ -23,6 +23,9 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( "SET @@SQL_MODE = REPLACE(@@SQL_MODE, 'ORACLE', '');" )}, + {C_STRING_WITH_LEN( + "SET @@OLD_MODE = CONCAT(@@OLD_MODE, ',UTF8_IS_UTF8MB3');" + )}, {C_STRING_WITH_LEN( "create table if not exists mysql.spider_xa(" " format_id int not null default 0," diff --git a/support-files/mini-benchmark.sh b/support-files/mini-benchmark.sh index 18de6dbec51..9b7cb6dc698 100755 --- a/support-files/mini-benchmark.sh +++ b/support-files/mini-benchmark.sh @@ -10,6 +10,18 @@ display_help() { echo "regressions." echo echo "optional arguments:" + echo " --name STRING identifier for the benchmark, added to the " + echo " folder name and (if --log is set) the log file " + echo " --threads \"STRING\" quoted string of space-separated integers " + echo " representing the threads to run." + echo " example: --threads \"1 32 64 128\"" + echo " default: \"1 2 4 8 16\"" + echo " --duration INTEGER duration of each thread run in seconds" + echo " default: 60" + echo " --workload STRING sysbench workload to execute" + echo " default: oltp_read_write" + echo " --log logs the mini-benchmark stdout/stderr into the" + echo " benchmark folder." echo " --perf measure CPU cycles and instruction count in for " echo " sysbench runs" echo " --perf-flamegraph record performance counters in perf.data.* and" @@ -17,6 +29,12 @@ display_help() { echo " -h, --help display this help and exit" } +# Default parameters +BENCHMARK_NAME='mini-benchmark' +THREADS='1 2 4 8 16' +DURATION=60 +WORKLOAD='oltp_read_write' + while : do case "$1" in @@ -28,6 +46,31 @@ do display_version exit 0 ;; + --name) + shift + BENCHMARK_NAME+='-' + BENCHMARK_NAME+=$1 + shift + ;; + --threads) + shift + THREADS=$1 + shift + ;; + --duration) + shift + DURATION=$1 + shift + ;; + --workload) + shift + WORKLOAD=$1 + shift + ;; + --log) + LOG=true + shift + ;; --perf) PERF=true shift @@ -47,6 +90,13 @@ do esac done +# Save results of this run in a subdirectory so that they are not overwritten by +# the next run +TIMESTAMP="$(date -Iseconds)" +mkdir "$BENCHMARK_NAME-$TIMESTAMP" +cd "$BENCHMARK_NAME-$TIMESTAMP" || exit 1 + +( # Check that the dependencies of this script are available if [ ! -e /usr/bin/pgrep ] then @@ -62,6 +112,7 @@ fi # If there are multiple processes, assume the last one is the actual server and # any potential other ones were just part of the service wrapper chain +# shellcheck disable=SC2005 MARIADB_SERVER_PID="$(echo "$(pgrep -f mariadbd || pgrep -f mysqld)" | tail -n 1)" if [ -z "$MARIADB_SERVER_PID" ] @@ -102,12 +153,13 @@ then echo "Ensure the MariaDB Server debug symbols are installed" for x in $(ldd /usr/sbin/mariadbd | grep -oE " /.* ") do - rpm -q --whatprovides --qf '%{name}' $x | cut -d : -f 1 + rpm -q --whatprovides --qf '%{name}' "$x" | cut -d : -f 1 done | sort -u > mariadbd-dependencies.txt # shellcheck disable=SC2046 debuginfo-install -y mariadb-server $(cat mariadbd-dependencies.txt) - - if [ ! $(perf record echo "testing perf" > /dev/null 2>&1) ] + + perf record echo "testing perf" > /dev/null 2>&1 + if [ $? -ne 0 ] then echo "perf does not have permission to run on this system. Skipping." PERF="" @@ -120,7 +172,8 @@ elif [ -e /usr/bin/perf ] then # If flamegraphs were not requested, log normal perf counters if possible - if [ ! $(perf stat echo "testing perf" > /dev/null 2>&1) ] + perf stat echo "testing perf" > /dev/null 2>&1 + if [ $? -ne 0 ] then echo "perf does not have permission to run on this system. Skipping." PERF="" @@ -156,28 +209,23 @@ mariadb -e " CREATE USER IF NOT EXISTS sbtest@localhost; GRANT ALL PRIVILEGES ON sbtest.* TO sbtest@localhost" -sysbench oltp_read_write prepare --tables=20 --table-size=100000 | tee sysbench-prepare.log +sysbench "$WORKLOAD" prepare --tables=20 --table-size=100000 | tee sysbench-prepare.log sync && sleep 1 # Ensure writes were propagated to disk -# Save results of this run in a subdirectory so that they are not overwritten by -# the next run -TIMESTAMP="$(date -Iseconds)" -mkdir "mini-benchmark-$TIMESTAMP" -cd "mini-benchmark-$TIMESTAMP" || exit 1 - # Run benchmark with increasing thread counts. The MariaDB Server will be using # around 300 MB of RAM and mostly reading and writing in RAM, so I/O usage is # also low. The benchmark will most likely be CPU bound to due to the load # profile, and also guaranteed to be CPU bound because of being limited to a # single CPU with 'tasksel'. -for t in 1 2 4 8 16 +for t in $THREADS do # Prepend command with perf if defined - # Output stderr to stdout as perf outpus everything in stderr - $PERF $TASKSET_SYSBENCH sysbench oltp_read_write run --threads=$t --time=60 --report-interval=10 2>&1 | tee sysbench-run-$t.log + # Output stderr to stdout as perf outputs everything in stderr + # shellcheck disable=SC2086 + $PERF $TASKSET_SYSBENCH sysbench "$WORKLOAD" run --threads=$t --time=$DURATION --report-interval=10 2>&1 | tee sysbench-run-$t.log done -sysbench oltp_read_write cleanup --tables=20 | tee sysbench-cleanup.log +sysbench "$WORKLOAD" cleanup --tables=20 | tee sysbench-cleanup.log # Store results from 4 thread run in a Gitlab-CI compatible metrics file grep -oE '[a-z]+:[ ]+[0-9.]+' sysbench-run-4.log | sed -r 's/\s+/ /g' | tail -n 15 > metrics.txt @@ -197,10 +245,10 @@ then # Final verdict based on cpu cycle count RESULT="$(grep -h -e cycles sysbench-run-*.log | sort -k 1 | awk '{s+=$1}END{print s}')" - if [ "$RESULT" -gt 850000000000 ] + if [ "$RESULT" -gt 850 ] then echo # Newline improves readability - echo "Benchmark exceeded 8.5 billion cpu cycles, performance most likely regressed!" + echo "Benchmark exceeded 850 billion cpu cycles, performance most likely regressed!" exit 1 fi fi @@ -216,12 +264,12 @@ if [ "$PERF_RECORD" == true ] then for f in perf.data.* do - perf script -i $f | stackcollapse-perf.pl | flamegraph.pl --width 3000 > $f.svg + perf script -i "$f" | stackcollapse-perf.pl | flamegraph.pl --width 1800 > "$f".svg done - echo "Flamegraphs stored in folder mini-benchmark-$TIMESTAMP/" + echo "Flamegraphs stored in folder $BENCHMARK_NAME-$TIMESTAMP/" fi -# Fallback if CPU cycle count not availalbe: final verdict based on peak QPS +# Fallback if CPU cycle count not available: final verdict based on peak QPS RESULT="$(sort -k 9 -h sysbench-run-*.log | tail -n 1 | grep -oE "qps: [0-9]+" | grep -oE "[0-9]+")" case $RESULT in ''|*[!0-9]*) @@ -240,3 +288,6 @@ case $RESULT in fi ;; esac +# Record the output into the log file, if requested +) 2>&1 | ($LOG && tee "$BENCHMARK_NAME"-"$TIMESTAMP".log) +