diff --git a/.clang-format b/.clang-format index 7ce45951173..3633507cb13 100644 --- a/.clang-format +++ b/.clang-format @@ -70,7 +70,6 @@ IndentPPDirectives: None IndentWidth: 2 IndentWrappedFunctionNames: false KeepEmptyLinesAtTheStartOfBlocks: true -Language: Cpp MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 diff --git a/CMakeLists.txt b/CMakeLists.txt index 49769e2b303..6477c4042d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -199,8 +199,9 @@ OPTION(NOT_FOR_DISTRIBUTION "Allow linking with GPLv2-incompatible system librar # Can be switched on only for debug build. # OPTION(WITH_PROTECT_STATEMENT_MEMROOT "Enable protection of statement's memory root after first SP/PS execution. Turned into account only for debug build" OFF) -IF (CMAKE_BUILD_TYPE MATCHES "Debug" AND WITH_PROTECT_STATEMENT_MEMROOT) - ADD_DEFINITIONS(-DPROTECT_STATEMENT_MEMROOT) +IF (WITH_PROTECT_STATEMENT_MEMROOT) + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DPROTECT_STATEMENT_MEMROOT") + SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DPROTECT_STATEMENT_MEMROOT") ENDIF() INCLUDE(check_compiler_flag) diff --git a/README.md b/README.md index 58dbf105fb9..5fe95f46a6b 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Code status: * [![Appveyor CI status](https://ci.appveyor.com/api/projects/status/4u6pexmtpuf8jq66?svg=true)](https://ci.appveyor.com/project/rasmushoj/server) ci.appveyor.com -## MariaDB: The open source relational database +## MariaDB: The innovative open source database MariaDB was designed as a drop-in replacement of MySQL(R) with more features, new storage engines, fewer bugs, and better performance. @@ -33,28 +33,23 @@ https://mariadb.com/kb/en/mariadb-versus-mysql-compatibility/ https://mariadb.com/kb/en/new-and-old-releases/ +Getting the code, building it and testing it +--------------------------------------------------------------- + +Refer to the following guide: https://mariadb.org/get-involved/getting-started-for-developers/get-code-build-test/ which outlines how to correctly build the source code and run the MariaDB testing framework. + Help ----- More help is available from the Maria Discuss mailing list -https://launchpad.net/~maria-discuss, MariaDB's Zulip +https://lists.mariadb.org/postorius/lists/discuss.lists.mariadb.org/ and MariaDB's Zulip instance, https://mariadb.zulipchat.com/ -Live QA for beginner contributors ----- -MariaDB has a dedicated time each week when we answer new contributor questions live on Zulip. -From 8:00 to 10:00 UTC on Mondays, and 10:00 to 12:00 UTC on Thursdays, -anyone can ask any questions they’d like, and a live developer will be available to assist. - -New contributors can ask questions any time, but we will provide immediate feedback during that interval. - Licensing --------- *************************************************************************** -NOTE: - MariaDB is specifically available only under version 2 of the GNU General Public License (GPLv2). (I.e. Without the "any later version" clause.) This is inherited from MySQL. Please see the README file in diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index 69bd3cd7b92..c518cb23e78 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -1405,7 +1405,9 @@ static void usage(void) refresh Flush all tables and close and open logfiles\n\ shutdown Take server down\n\ status Gives a short status message from the server\n\ + start-all-slaves Start all slaves\n\ start-slave Start slave\n\ + stop-all-slaves Stop all slaves\n\ stop-slave Stop slave\n\ variables Prints variables available\n\ version Get version info from server"); diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 3f53c51de9e..fa1c8542220 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -397,7 +397,7 @@ enum enum_commands { Q_IF, Q_DISABLE_PARSING, Q_ENABLE_PARSING, Q_REPLACE_REGEX, Q_REMOVE_FILE, Q_FILE_EXIST, - Q_WRITE_FILE, Q_COPY_FILE, Q_PERL, Q_DIE, Q_EXIT, Q_SKIP, + Q_WRITE_FILE, Q_WRITE_LINE, Q_COPY_FILE, Q_PERL, Q_DIE, Q_EXIT, Q_SKIP, Q_CHMOD_FILE, Q_APPEND_FILE, Q_CAT_FILE, Q_DIFF_FILES, Q_SEND_QUIT, Q_CHANGE_USER, Q_MKDIR, Q_RMDIR, Q_LIST_FILES, Q_LIST_FILES_WRITE_FILE, Q_LIST_FILES_APPEND_FILE, @@ -500,6 +500,7 @@ const char *command_names[]= "remove_file", "file_exists", "write_file", + "write_line", "copy_file", "perl", "die", @@ -1534,7 +1535,6 @@ void free_used_memory() void ha_pre_shutdown(); #endif - ATTRIBUTE_NORETURN static void cleanup_and_exit(int exit_code, bool called_from_die) { @@ -4369,6 +4369,49 @@ void do_write_file(struct st_command *command) do_write_file_command(command, FALSE); } +/** + Write a line to the start of the file. + Truncates existing file, creates new one if it doesn't exist. + + Usage + write_line ; + + Example + --write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + + @note Both the file and the line parameters are evaluated + (can be variables). + + @note This is a better alternative to + exec echo > file, as it doesn't depend on shell, + and can better handle sporadic file access errors caused + by antivirus or backup software on Windows. +*/ +void do_write_line(struct st_command *command) +{ + DYNAMIC_STRING ds_line; + DYNAMIC_STRING ds_filename; + + struct command_arg write_line_args[] = { + { "line", ARG_STRING, FALSE, &ds_line, "line to add" }, + { "filename", ARG_STRING, TRUE, &ds_filename, "File to write to" }, + }; + DBUG_ENTER("do_write_line"); + + check_command_args(command, + command->first_argument, + write_line_args, + sizeof(write_line_args)/sizeof(struct command_arg), + ' '); + + if (bad_path(ds_filename.str)) + DBUG_VOID_RETURN; + dynstr_append_mem(&ds_line, "\n", 1); + str_to_file2(ds_filename.str, ds_line.str, ds_line.length, FALSE); + dynstr_free(&ds_filename); + dynstr_free(&ds_line); + DBUG_VOID_RETURN; +} /* SYNOPSIS @@ -5286,7 +5329,11 @@ void do_shutdown_server(struct st_command *command) */ if (timeout && mysql_shutdown(mysql, SHUTDOWN_DEFAULT)) - die("mysql_shutdown failed"); + { + handle_error(command, mysql_errno(mysql), mysql_error(mysql), + mysql_sqlstate(mysql), &ds_res); + DBUG_VOID_RETURN; + } if (!timeout || wait_until_dead(pid, timeout)) { @@ -7495,7 +7542,7 @@ void str_to_file2(const char *fname, char *str, size_t size, my_bool append) die("Could not open '%s' for writing, errno: %d", buff, errno); if (append && my_seek(fd, 0, SEEK_END, MYF(0)) == MY_FILEPOS_ERROR) die("Could not find end of file '%s', errno: %d", buff, errno); - if (my_write(fd, (uchar*)str, size, MYF(MY_WME|MY_FNABP))) + if (size > 0 && my_write(fd, (uchar*)str, size, MYF(MY_WME|MY_FNABP))) die("write failed, errno: %d", errno); my_close(fd, MYF(0)); } @@ -8290,7 +8337,7 @@ static int match_expected_error(struct st_command *command, SYNOPSIS handle_error() - q - query context + command - command err_errno - error number err_error - error message err_sqlstate - sql state @@ -10291,6 +10338,7 @@ int main(int argc, char **argv) break; case Q_FILE_EXIST: do_file_exist(command); break; case Q_WRITE_FILE: do_write_file(command); break; + case Q_WRITE_LINE: do_write_line(command); break; case Q_APPEND_FILE: do_append_file(command); break; case Q_DIFF_FILES: do_diff_files(command); break; case Q_SEND_QUIT: do_send_quit(command); break; diff --git a/cmake/libutils.cmake b/cmake/libutils.cmake index 74853c36a74..3263c08ec44 100644 --- a/cmake/libutils.cmake +++ b/cmake/libutils.cmake @@ -379,5 +379,11 @@ FUNCTION (MAYBE_DISABLE_IPO target) INTERPROCEDURAL_OPTIMIZATION_RELEASE OFF INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO OFF INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL OFF) + IF(CMAKE_CONFIGURATION_TYPES) + FOREACH(cfg ${CMAKE_CONFIGURATION_TYPES}) + STRING(TOUPPER "${cfg}" cfg_upper) + SET_TARGET_PROPERTIES(${target} PROPERTIES INTERPROCEDURAL_OPTIMIZATION_${cfg_upper} OFF) + ENDFOREACH() + ENDIF() ENDIF() ENDFUNCTION() diff --git a/cmake/mariadb_connector_c.cmake b/cmake/mariadb_connector_c.cmake index a9b103345cd..b4f56597775 100644 --- a/cmake/mariadb_connector_c.cmake +++ b/cmake/mariadb_connector_c.cmake @@ -40,6 +40,13 @@ SET(CLIENT_PLUGIN_PVIO_SOCKET STATIC) MESSAGE("== Configuring MariaDB Connector/C") ADD_SUBDIRECTORY(libmariadb) +IF(MSVC AND TARGET mariadb_obj AND TARGET mariadbclient) + # With MSVC, do not produce LTCG-compiled static client libraries. + # They are not usable by end-users, being tied to exact compiler version + MAYBE_DISABLE_IPO(mariadb_obj) + MAYBE_DISABLE_IPO(mariadbclient) +ENDIF() + IF(UNIX) INSTALL(CODE "EXECUTE_PROCESS( COMMAND ${CMAKE_COMMAND} -E make_directory \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${INSTALL_BINDIR}) diff --git a/configure.cmake b/configure.cmake index c2706b50502..33f0ad96735 100644 --- a/configure.cmake +++ b/configure.cmake @@ -984,3 +984,8 @@ IF(have_C__Werror) ) SET(CMAKE_REQUIRED_FLAGS ${SAVE_CMAKE_REQUIRED_FLAGS}) ENDIF() + +IF(CMAKE_C_COMPILER_ID MATCHES "Intel") + MY_CHECK_AND_SET_COMPILER_FLAG("-no-ansi-alias") + MY_CHECK_AND_SET_COMPILER_FLAG("-fp-model precise") +ENDIF() diff --git a/include/my_sys.h b/include/my_sys.h index 540432cebc5..17ddccbec58 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -655,6 +655,7 @@ extern size_t my_fwrite(FILE *stream,const uchar *Buffer,size_t Count, myf MyFlags); extern my_off_t my_fseek(FILE *stream,my_off_t pos,int whence,myf MyFlags); extern my_off_t my_ftell(FILE *stream,myf MyFlags); +extern void (*my_sleep_for_space)(unsigned int seconds); /* implemented in my_memmem.c */ extern void *my_memmem(const void *haystack, size_t haystacklen, diff --git a/mysql-test/collections/buildbot_suites.bat b/mysql-test/collections/buildbot_suites.bat index d4a6e665840..13ea5ddb949 100644 --- a/mysql-test/collections/buildbot_suites.bat +++ b/mysql-test/collections/buildbot_suites.bat @@ -1,5 +1,5 @@ if "%MTR_PARALLEL%"=="" set MTR_PARALLEL=%NUMBER_OF_PROCESSORS% -perl mysql-test-run.pl --verbose-restart --force --suite-timeout=120 --max-test-fail=10 --retry=3 --suite=^ +perl mysql-test-run.pl --force --suite-timeout=120 --max-test-fail=10 --retry=3 --suite=^ vcol,gcol,perfschema,^ main,^ innodb,^ diff --git a/mysql-test/include/commit.inc b/mysql-test/include/commit.inc index c696613dab3..132fdcff7bd 100644 --- a/mysql-test/include/commit.inc +++ b/mysql-test/include/commit.inc @@ -613,13 +613,17 @@ call p_verify_status_increment(2, 0, 2, 0); drop table t2; set sql_mode=no_engine_substitution; create temporary table t2 (a int); -call p_verify_status_increment(1, 0, 0, 0); +# One commit for the create temporary table, and two for committing the +# read of the stored procedure from Aria table (creating temporary table +# clears the sp cache). +call p_verify_status_increment(3, 0, 2, 0); set sql_mode=default; --echo # 19. A function changes temp-trans-table. --echo # select f1(); ---echo # Two commits because a binary log record is written -call p_verify_status_increment(2, 0, 1, 0); +--echo # Two commits because a binary log record is written, and another two +--echo # as the function f1() is reloaded after creating temporary table. +call p_verify_status_increment(4, 0, 3, 0); commit; call p_verify_status_increment(2, 0, 1, 0); @@ -672,9 +676,11 @@ call p_verify_status_increment(2, 0, 1, 0); --echo # 25. DDL: DROP TEMPORARY TABLE, does not start a transaction --echo # drop temporary table t2; -call p_verify_status_increment(1, 0, 1, 0); +# Dropping temporary table clears SP caches, so get another two commit +# increments from loading the p_verify_status_increment procedure. +call p_verify_status_increment(3, 0, 2, 0); commit; -call p_verify_status_increment(1, 0, 1, 0); +call p_verify_status_increment(1, 0, 0, 0); --echo # 26. Verify that SET AUTOCOMMIT issues an implicit commit --echo # @@ -721,7 +727,9 @@ call p_verify_status_increment(1, 0, 1, 0); create table t2 (a int); call p_verify_status_increment(0, 0, 0, 0); do (select f1() from t1 where a=2); -call p_verify_status_increment(2, 2, 2, 2); +# Again extra 2 commit increments from re-loading function f1 after +# dropping temporary table. +call p_verify_status_increment(4, 2, 4, 2); commit; call p_verify_status_increment(2, 2, 2, 2); diff --git a/mysql-test/include/crash_mysqld.inc b/mysql-test/include/crash_mysqld.inc index 4190d24d801..89bc8ced416 100644 --- a/mysql-test/include/crash_mysqld.inc +++ b/mysql-test/include/crash_mysqld.inc @@ -4,7 +4,7 @@ --source include/not_embedded.inc # Write file to make mysql-test-run.pl expect crash and restart ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect # Setup the mysqld to crash at shutdown SET debug_dbug="d,crash_shutdown"; diff --git a/mysql-test/include/default_mysqld.cnf b/mysql-test/include/default_mysqld.cnf index 89d0d779627..97e69c7b0b1 100644 --- a/mysql-test/include/default_mysqld.cnf +++ b/mysql-test/include/default_mysqld.cnf @@ -91,7 +91,7 @@ loose-performance-schema-events-statements-history-size=10 loose-performance-schema-events-statements-history-long-size=1000 loose-performance-schema-events-transactions-history-size=10 loose-performance-schema-events-transactions-history-long-size=1000 -loose-performance-schema-max-thread-instances=200 +loose-performance-schema-max-thread-instances=400 loose-performance-schema-session-connect-attrs-size=2048 loose-performance-schema-max-metadata-locks=10000 diff --git a/mysql-test/include/expect_crash.inc b/mysql-test/include/expect_crash.inc index b4bd9828a08..56abc88ae24 100644 --- a/mysql-test/include/expect_crash.inc +++ b/mysql-test/include/expect_crash.inc @@ -2,4 +2,4 @@ --let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/$_expect_file_name.expect # There should be a debug crash after using this .inc file ---exec echo "wait" > $_expect_file_name +--write_line wait $_expect_file_name diff --git a/mysql-test/include/kill_and_restart_mysqld.inc b/mysql-test/include/kill_and_restart_mysqld.inc index b67fb7350b4..50b28bcd494 100644 --- a/mysql-test/include/kill_and_restart_mysqld.inc +++ b/mysql-test/include/kill_and_restart_mysqld.inc @@ -7,7 +7,7 @@ if (!$restart_parameters) --let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.$_server_id.expect --echo # Kill and $restart_parameters ---exec echo "$restart_parameters" > $_expect_file_name +--write_line "$restart_parameters" $_expect_file_name --shutdown_server 0 --source include/wait_until_disconnected.inc --enable_reconnect diff --git a/mysql-test/include/kill_galera.inc b/mysql-test/include/kill_galera.inc index aba672d8a89..887e21f5f79 100644 --- a/mysql-test/include/kill_galera.inc +++ b/mysql-test/include/kill_galera.inc @@ -3,7 +3,7 @@ # Write file to make mysql-test-run.pl expect the crash, but don't start it --let $_expect_file_name= `select regexp_replace(@@tmpdir, '^.*/','')` --let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/$_expect_file_name.expect ---exec echo "wait" > $_expect_file_name +--write_line wait $_expect_file_name # Kill the connected server --disable_reconnect diff --git a/mysql-test/include/kill_mysqld.inc b/mysql-test/include/kill_mysqld.inc index 01ee7f82bdc..a41af2d74a6 100644 --- a/mysql-test/include/kill_mysqld.inc +++ b/mysql-test/include/kill_mysqld.inc @@ -2,6 +2,6 @@ --let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/$_expect_file_name.expect --echo # Kill the server ---exec echo "wait" > $_expect_file_name +--write_line wait $_expect_file_name --shutdown_server 0 --source include/wait_until_disconnected.inc diff --git a/mysql-test/include/rpl_change_topology.inc b/mysql-test/include/rpl_change_topology.inc index b63700b059b..ddaf90a9cf0 100644 --- a/mysql-test/include/rpl_change_topology.inc +++ b/mysql-test/include/rpl_change_topology.inc @@ -96,10 +96,11 @@ # Remove whitespace from $rpl_topology --let $rpl_topology= `SELECT REPLACE('$rpl_topology', ' ', '')` +--source include/slow_environ.inc + --let $include_filename= rpl_change_topology.inc [new topology=$rpl_topology] --source include/begin_include_file.inc - if ($rpl_debug) { --echo ---- Check input ---- @@ -235,11 +236,11 @@ if (!$rpl_skip_change_master) } if ($rpl_master_log_file) { - eval CHANGE MASTER TO MASTER_HOST = '127.0.0.1', MASTER_PORT = $_rpl_port, MASTER_USER = 'root', MASTER_LOG_FILE = '$_rpl_master_log_file'$_rpl_master_log_pos, MASTER_CONNECT_RETRY = 1, MASTER_USE_GTID=NO; + eval CHANGE MASTER TO MASTER_HOST = '127.0.0.1', MASTER_PORT = $_rpl_port, MASTER_USER = 'root', MASTER_LOG_FILE = '$_rpl_master_log_file'$_rpl_master_log_pos, MASTER_CONNECT_RETRY = 1$_timeout_adjustment, MASTER_USE_GTID=NO; } if (!$rpl_master_log_file) { - eval CHANGE MASTER TO MASTER_HOST = '127.0.0.1', MASTER_PORT = $_rpl_port, MASTER_USER = 'root', MASTER_CONNECT_RETRY=1; + eval CHANGE MASTER TO MASTER_HOST = '127.0.0.1', MASTER_PORT = $_rpl_port, MASTER_USER = 'root', MASTER_CONNECT_RETRY=1$_timeout_adjustment; } } if ($_rpl_master == '') diff --git a/mysql-test/include/rpl_start_server.inc b/mysql-test/include/rpl_start_server.inc index 932fc9da7ef..0479dbbd8ac 100644 --- a/mysql-test/include/rpl_start_server.inc +++ b/mysql-test/include/rpl_start_server.inc @@ -49,7 +49,7 @@ if ($rpl_server_parameters) --source include/rpl_connection.inc # Write file to make mysql-test-run.pl start up the server again ---exec echo "$_rpl_start_server_command" > $MYSQLTEST_VARDIR/tmp/mysqld.$rpl_server_number.expect +--write_line "$_rpl_start_server_command" $MYSQLTEST_VARDIR/tmp/mysqld.$rpl_server_number.expect if (!$rpl_server_error) { diff --git a/mysql-test/include/rpl_stop_server.inc b/mysql-test/include/rpl_stop_server.inc index 470e86a139d..1e4a64cca25 100644 --- a/mysql-test/include/rpl_stop_server.inc +++ b/mysql-test/include/rpl_stop_server.inc @@ -44,7 +44,7 @@ if ($rpl_debug) # Write file to make mysql-test-run.pl expect the "crash", but don't start # it until it's told to ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.$rpl_server_number.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.$rpl_server_number.expect # Send shutdown to the connected server and give # it 60 seconds (of mysqltest's default) to die before zapping it diff --git a/mysql-test/include/search_pattern_in_file.inc b/mysql-test/include/search_pattern_in_file.inc index 1c23b356c4d..ab3c95fce3c 100644 --- a/mysql-test/include/search_pattern_in_file.inc +++ b/mysql-test/include/search_pattern_in_file.inc @@ -36,7 +36,7 @@ # let SEARCH_FILE= $error_log; # # Stop the server # let $restart_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect; -# --exec echo "wait" > $restart_file +# --write_line wait $restart_file # --shutdown_server # --source include/wait_until_disconnected.inc # diff --git a/mysql-test/include/shutdown_mysqld.inc b/mysql-test/include/shutdown_mysqld.inc index fc2972560c3..1684d81970a 100644 --- a/mysql-test/include/shutdown_mysqld.inc +++ b/mysql-test/include/shutdown_mysqld.inc @@ -24,18 +24,15 @@ if ($rpl_inited) # Write file to make mysql-test-run.pl expect the "crash", but don't start it --let $_expect_file_name= `select regexp_replace(@@tmpdir, '^.*/','')` --let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/$_expect_file_name.expect ---exec echo "wait" > $_expect_file_name +--write_line wait $_expect_file_name # Avoid warnings from connection threads that does not have time to exit --disable_query_log set @@global.log_warnings=0; --enable_query_log ---let $server_shutdown_timeout= 60 -if ($VALGRIND_TEST) -{ - --let $server_shutdown_timeout= 300 -} +--source include/slow_environ.inc +--let $server_shutdown_timeout= 60$_timeout_adjustment if ($shutdown_timeout) { diff --git a/mysql-test/include/slow_environ.inc b/mysql-test/include/slow_environ.inc new file mode 100644 index 00000000000..761147fd288 --- /dev/null +++ b/mysql-test/include/slow_environ.inc @@ -0,0 +1,9 @@ +if (!$slow_environ_check) +{ + let $_timeout_adjustment=; + if (`select $VALGRIND_TEST + count(*) from information_schema.system_variables where variable_name='have_sanitizer' and global_value like '%SAN%'`) + { + let $_timeout_adjustment=0; + } + let $slow_environ_check=1; +} diff --git a/mysql-test/include/start_mysqld.inc b/mysql-test/include/start_mysqld.inc index 6e448cb2efd..91b06997d6e 100644 --- a/mysql-test/include/start_mysqld.inc +++ b/mysql-test/include/start_mysqld.inc @@ -21,7 +21,7 @@ if ($restart_bindir) if ($restart_parameters) { - --exec echo "$restart_cmd: $restart_parameters" > $_expect_file_name + --write_line "$restart_cmd: $restart_parameters" $_expect_file_name if (!$restart_noprint) { --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR $MYSQLTEST_VARDIR MYSQLTEST_VARDIR @@ -34,7 +34,7 @@ if ($restart_parameters) } if (!$restart_parameters) { - --exec echo "$restart_cmd" > $_expect_file_name + --write_line "$restart_cmd" $_expect_file_name if ($restart_noprint < 2) { --exec echo "# $restart_cmd" diff --git a/mysql-test/include/stop_slave_io.inc b/mysql-test/include/stop_slave_io.inc index ddc83782311..a9d97f2f8a1 100644 --- a/mysql-test/include/stop_slave_io.inc +++ b/mysql-test/include/stop_slave_io.inc @@ -34,8 +34,17 @@ if (!$rpl_debug) --disable_query_log } - +let $_enable_warnings=0; +if ($rpl_allow_error) { + if ($ENABLED_WARNINGS) { + let $_enable_warnings=1; + disable_warnings; + } +} STOP SLAVE IO_THREAD; +if ($_enable_warnings) { + enable_warnings; +} --source include/wait_for_slave_io_to_stop.inc diff --git a/mysql-test/include/sync_slave_sql_with_io.inc b/mysql-test/include/sync_slave_sql_with_io.inc index 9efede9a61f..c16d28edbb9 100644 --- a/mysql-test/include/sync_slave_sql_with_io.inc +++ b/mysql-test/include/sync_slave_sql_with_io.inc @@ -25,11 +25,8 @@ let $_slave_timeout= $slave_timeout; if (!$_slave_timeout) { - let $_slave_timeout= 300; - if ($VALGRIND_TEST) - { - let $_slave_timeout= 1500; - } + source include/slow_environ.inc; + let $_slave_timeout= 300$_timeout_adjustment; } --let $_master_log_file= query_get_value(SHOW SLAVE STATUS, Master_Log_File, 1) diff --git a/mysql-test/include/sync_with_master_gtid.inc b/mysql-test/include/sync_with_master_gtid.inc index 777711b979c..0ca2c90784e 100644 --- a/mysql-test/include/sync_with_master_gtid.inc +++ b/mysql-test/include/sync_with_master_gtid.inc @@ -33,11 +33,8 @@ let $_slave_timeout= $slave_timeout; if (!$_slave_timeout) { - let $_slave_timeout= 120; - if ($VALGRIND_TEST) - { - let $_slave_timeout= 1200; - } + source include/slow_environ.inc; + let $_slave_timeout= 120$_timeout_adjustment; } --let $_result= `SELECT master_gtid_wait('$master_pos', $_slave_timeout)` diff --git a/mysql-test/include/wait_for_slave_param.inc b/mysql-test/include/wait_for_slave_param.inc index ed81c55963f..6802cd41203 100644 --- a/mysql-test/include/wait_for_slave_param.inc +++ b/mysql-test/include/wait_for_slave_param.inc @@ -49,11 +49,8 @@ let $_slave_timeout= $slave_timeout; if (!$_slave_timeout) { - let $_slave_timeout= 300; - if ($VALGRIND_TEST) - { - let $_slave_timeout= 1500; - } + source include/slow_environ.inc; + let $_slave_timeout= 300$_timeout_adjustment; } let $_slave_param_comparison= $slave_param_comparison; diff --git a/mysql-test/lib/My/Debugger.pm b/mysql-test/lib/My/Debugger.pm index d129aa09961..907638c9433 100644 --- a/mysql-test/lib/My/Debugger.pm +++ b/mysql-test/lib/My/Debugger.pm @@ -263,6 +263,7 @@ sub pre_setup() { $::opt_suite_timeout= 24 * 60; # in minutes $::opt_shutdown_timeout= ($interactive ? 24 * 60 : 3) * 60; # in seconds $::opt_start_timeout= $::opt_shutdown_timeout; # in seconds + $::opt_debug_sync_timeout= 3000; # in seconds } } diff --git a/mysql-test/main/commit_1innodb.result b/mysql-test/main/commit_1innodb.result index d090844cb74..973be9fde0d 100644 --- a/mysql-test/main/commit_1innodb.result +++ b/mysql-test/main/commit_1innodb.result @@ -634,7 +634,7 @@ SUCCESS drop table t2; set sql_mode=no_engine_substitution; create temporary table t2 (a int); -call p_verify_status_increment(1, 0, 0, 0); +call p_verify_status_increment(3, 0, 2, 0); SUCCESS set sql_mode=default; @@ -643,8 +643,9 @@ set sql_mode=default; select f1(); f1() 2 -# Two commits because a binary log record is written -call p_verify_status_increment(2, 0, 1, 0); +# Two commits because a binary log record is written, and another two +# as the function f1() is reloaded after creating temporary table. +call p_verify_status_increment(4, 0, 3, 0); SUCCESS commit; @@ -715,11 +716,11 @@ SUCCESS # 25. DDL: DROP TEMPORARY TABLE, does not start a transaction # drop temporary table t2; -call p_verify_status_increment(1, 0, 1, 0); +call p_verify_status_increment(3, 0, 2, 0); SUCCESS commit; -call p_verify_status_increment(1, 0, 1, 0); +call p_verify_status_increment(1, 0, 0, 0); SUCCESS # 26. Verify that SET AUTOCOMMIT issues an implicit commit @@ -801,7 +802,7 @@ call p_verify_status_increment(0, 0, 0, 0); SUCCESS do (select f1() from t1 where a=2); -call p_verify_status_increment(2, 2, 2, 2); +call p_verify_status_increment(4, 2, 4, 2); SUCCESS commit; diff --git a/mysql-test/main/constraints.result b/mysql-test/main/constraints.result index 143c22321ab..d2a19040083 100644 --- a/mysql-test/main/constraints.result +++ b/mysql-test/main/constraints.result @@ -235,3 +235,16 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop procedure sp; drop table t1; +# +# MDEV-33768: Memory leak found in the test main.constraints run with --ps-protocol against a server built with the option -DWITH_PROTECT_STATEMENT_MEMROOT +# This test case was added by reviewer's request. +# +PREPARE stmt FROM 'CREATE TABLE t1 (a INT)'; +EXECUTE stmt; +DROP TABLE t1; +EXECUTE stmt; +EXECUTE stmt; +ERROR 42S01: Table 't1' already exists +# Clean up +DROP TABLE t1; +DEALLOCATE PREPARE stmt; diff --git a/mysql-test/main/constraints.test b/mysql-test/main/constraints.test index 5c673f9be81..83f3394d6f6 100644 --- a/mysql-test/main/constraints.test +++ b/mysql-test/main/constraints.test @@ -189,3 +189,18 @@ call sp; show create table t1; drop procedure sp; drop table t1; + +--echo # +--echo # MDEV-33768: Memory leak found in the test main.constraints run with --ps-protocol against a server built with the option -DWITH_PROTECT_STATEMENT_MEMROOT +--echo # This test case was added by reviewer's request. +--echo # +PREPARE stmt FROM 'CREATE TABLE t1 (a INT)'; +EXECUTE stmt; +DROP TABLE t1; +EXECUTE stmt; +--error ER_TABLE_EXISTS_ERROR +EXECUTE stmt; + +--echo # Clean up +DROP TABLE t1; +DEALLOCATE PREPARE stmt; diff --git a/mysql-test/main/crash_commit_before.test b/mysql-test/main/crash_commit_before.test index 93b96de6e53..30b59ce4480 100644 --- a/mysql-test/main/crash_commit_before.test +++ b/mysql-test/main/crash_commit_before.test @@ -17,7 +17,7 @@ insert into t1 values(9); SET GLOBAL debug_dbug="d,crash_commit_before"; # Write file to make mysql-test-run.pl expect crash and restart ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect # Run the crashing query --error 2013 diff --git a/mysql-test/main/create.result b/mysql-test/main/create.result index d6c68fdd917..9db7d5ca844 100644 --- a/mysql-test/main/create.result +++ b/mysql-test/main/create.result @@ -1803,7 +1803,7 @@ show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `color` char(32) GENERATED ALWAYS AS (column_get(`dynamic_cols`,1 as char charset latin1)) STORED, - `cl` char(32) GENERATED ALWAYS AS (column_get(column_add(column_create(1,'blue' AS char charset latin1 ),2,'ttt'),`i` as char charset latin1)) STORED, + `cl` char(32) GENERATED ALWAYS AS (column_get(column_add(column_create(1,'blue' AS char charset latin1 collate latin1_swedish_ci ),2,'ttt'),`i` as char charset latin1)) STORED, `item_name` varchar(32) NOT NULL, `i` int(11) DEFAULT NULL, `dynamic_cols` blob DEFAULT NULL, diff --git a/mysql-test/main/dyncol.result b/mysql-test/main/dyncol.result index 88cec1c50f0..64ce60b4e45 100644 --- a/mysql-test/main/dyncol.result +++ b/mysql-test/main/dyncol.result @@ -150,7 +150,7 @@ select hex(COLUMN_CREATE(1, "afaf" AS char character set utf8, id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 select hex(column_create(1,'afaf' AS char charset utf8mb3 ,2,1212 AS unsigned int,3,1212 AS int,4,12.12 AS double,4 + 1,12.12 AS decimal,6,'2011-04-05' AS date,7,'- 0:45:49.000001' AS time,8,'2011-04-05 0:45:49.000001' AS datetime)) AS `ex` +Note 1003 select hex(column_create(1,'afaf' AS char charset utf8mb3 collate utf8mb3_general_ci ,2,1212 AS unsigned int,3,1212 AS int,4,12.12 AS double,4 + 1,12.12 AS decimal,6,'2011-04-05' AS date,7,'- 0:45:49.000001' AS time,8,'2011-04-05 0:45:49.000001' AS datetime)) AS `ex` select hex(column_create(1, 0.0 AS decimal)); hex(column_create(1, 0.0 AS decimal)) 000100010004 @@ -354,7 +354,7 @@ select column_get(column_create(1, "1212" AS char charset utf8), 1 as char chars id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 select column_get(column_create(1,'1212' AS char charset utf8mb3 ),1 as char charset utf8mb3) AS `ex` +Note 1003 select column_get(column_create(1,'1212' AS char charset utf8mb3 collate utf8mb3_general_ci ),1 as char charset utf8mb3) AS `ex` select column_get(column_create(1, 1212 AS unsigned int), 1 as char charset utf8) as ex; ex 1212 @@ -414,7 +414,7 @@ select column_get(column_create(1, "1212" AS char charset utf8), 1 as char chars id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 select column_get(column_create(1,'1212' AS char charset utf8mb3 ),1 as char charset binary) AS `ex` +Note 1003 select column_get(column_create(1,'1212' AS char charset utf8mb3 collate utf8mb3_general_ci ),1 as char charset binary) AS `ex` # # column get real # @@ -1882,7 +1882,7 @@ drop table t1; create view v1 as select column_get(column_add(column_create(1 , 'blue' as char), 2, 'ttt'), 1 as char); show create view v1; View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select column_get(column_add(column_create(1,'blue' AS char charset utf8mb3 ),2,'ttt'),1 as char charset utf8mb3) AS `Name_exp_1` utf8mb3 utf8mb3_general_ci +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select column_get(column_add(column_create(1,'blue' AS char charset utf8mb3 collate utf8mb3_general_ci ),2,'ttt'),1 as char charset utf8mb3) AS `Name_exp_1` utf8mb3 utf8mb3_general_ci select * from v1; Name_exp_1 blue @@ -1949,3 +1949,23 @@ ex # # End of 10.4 tests # +# +# Start of 10.5 tests +# +# +# Start of 10.5 tests +# +# +# MDEV-33788 HEX(COLUMN_CREATE(.. AS CHAR ...)) fails with --view-protocol +# +SELECT hex(column_create(1,'a' AS CHAR CHARACTER SET utf8mb3 COLLATE utf8mb3_bin)) AS ex; +ex +0001000100035361 +SELECT hex(column_add(column_create( +1, 'a' AS CHAR CHARACTER SET utf8mb3 COLLATE utf8mb3_bin), +2, 'b' AS CHAR CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci)) AS ex; +ex +00020001000302001353612162 +# +# Start of 10.5 tests +# diff --git a/mysql-test/main/dyncol.test b/mysql-test/main/dyncol.test index 8b3164217d1..1343025d5c5 100644 --- a/mysql-test/main/dyncol.test +++ b/mysql-test/main/dyncol.test @@ -1000,3 +1000,24 @@ SELECT HEX(COLUMN_ADD(COLUMN_CREATE(1,10),2,NULL,1,NULL)) as ex; --echo # --echo # End of 10.4 tests --echo # + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-33788 HEX(COLUMN_CREATE(.. AS CHAR ...)) fails with --view-protocol +--echo # + +SELECT hex(column_create(1,'a' AS CHAR CHARACTER SET utf8mb3 COLLATE utf8mb3_bin)) AS ex; +SELECT hex(column_add(column_create( + 1, 'a' AS CHAR CHARACTER SET utf8mb3 COLLATE utf8mb3_bin), + 2, 'b' AS CHAR CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci)) AS ex; + +--echo # +--echo # Start of 10.5 tests +--echo # diff --git a/mysql-test/main/empty_server_name-8224.test b/mysql-test/main/empty_server_name-8224.test index 5c5140be2e0..31760713bc8 100644 --- a/mysql-test/main/empty_server_name-8224.test +++ b/mysql-test/main/empty_server_name-8224.test @@ -3,10 +3,10 @@ # --source include/not_embedded.inc create server '' foreign data wrapper w2 options (host '127.0.0.1'); ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --shutdown_server --source include/wait_until_disconnected.inc ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect -- enable_reconnect -- source include/wait_until_connected_again.inc diff --git a/mysql-test/main/empty_string_literal.result b/mysql-test/main/empty_string_literal.result index 71b0869cb2a..447bad8a75a 100644 --- a/mysql-test/main/empty_string_literal.result +++ b/mysql-test/main/empty_string_literal.result @@ -208,12 +208,13 @@ t1 CREATE TABLE `t1` ( KEY `a` (`a`,`b`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table t1; +set sql_mode= default; # # MDEV-33460 select '123' 'x'; unexpected result # SELECT ''; -NULL -NULL + + SELECT '' 'b' 'c'; bc bc diff --git a/mysql-test/main/empty_string_literal.test b/mysql-test/main/empty_string_literal.test index 3320841fb42..e3ae009445b 100644 --- a/mysql-test/main/empty_string_literal.test +++ b/mysql-test/main/empty_string_literal.test @@ -25,12 +25,15 @@ flush tables; update t1 set a = 2; show create table t1; drop table t1; +set sql_mode= default; --echo # --echo # MDEV-33460 select '123' 'x'; unexpected result --echo # +--disable_view_protocol SELECT ''; +--enable_view_protocol SELECT '' 'b' 'c'; SELECT '' '' 'c'; SELECT 'a' '' 'c'; diff --git a/mysql-test/main/func_in.result b/mysql-test/main/func_in.result index b3865babca2..1ddb5257314 100644 --- a/mysql-test/main/func_in.result +++ b/mysql-test/main/func_in.result @@ -971,6 +971,84 @@ c1 9223372036854775808 drop table `a`; # +# MDEV-18319 BIGINT UNSIGNED Performance issue +# +CREATE OR REPLACE TABLE t1 ( +id bigint(20) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY +); +FOR i IN 0..255 +DO +INSERT INTO t1 VALUES (); +END FOR +$$ +SELECT MIN(id), MAX(id), COUNT(*) FROM t1; +MIN(id) MAX(id) COUNT(*) +1 256 256 +EXPLAIN SELECT id FROM t1 WHERE id IN (1,2); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range PRIMARY PRIMARY 8 NULL 2 Using where; Using index +EXPLAIN SELECT id FROM t1 WHERE id IN (9223372036854775806, 9223372036854775807); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range PRIMARY PRIMARY 8 NULL 2 Using where; Using index +EXPLAIN SELECT id FROM t1 WHERE id IN (9223372036854775807, 9223372036854775808); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range PRIMARY PRIMARY 8 NULL 2 Using where; Using index +DROP TABLE t1; +# +# MDEV-18898 SELECT using wrong index when using operator IN with mixed types +# +CREATE TEMPORARY TABLE t1 ( +id int(10) unsigned NOT NULL AUTO_INCREMENT, +name varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, +PRIMARY KEY (`id`), +UNIQUE KEY `name` (`name`) +); +FOR i IN 1..255 +DO +INSERT INTO t1 VALUES (i, MD5(i)); +END FOR +$$ +# +# Constants alone +# +ANALYZE SELECT id, name FROM t1 WHERE id = 1; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 NULL 100.00 NULL +ANALYZE SELECT id, name FROM t1 WHERE id = '2'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 NULL 100.00 NULL +# +# Two constants using IN +# +ANALYZE SELECT id, name FROM t1 WHERE id IN (1, 2); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 2.00 100.00 100.00 Using index condition +ANALYZE SELECT id, name FROM t1 WHERE id IN ('1', 2) /* Used a wrong index */; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 2.00 100.00 100.00 Using index condition +ANALYZE SELECT id, name FROM t1 WHERE id IN (1, '2') /* Used a wrong index */; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 2.00 100.00 100.00 Using index condition +ANALYZE SELECT id, name FROM t1 WHERE id IN ('1', '2'); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 2.00 100.00 100.00 Using index condition +# +# Two constants using OR +# +ANALYZE SELECT id, name FROM t1 WHERE id = 1 OR id = 2; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 2.00 100.00 100.00 Using index condition +ANALYZE SELECT id, name FROM t1 WHERE id = '1' OR id = '2'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 2.00 100.00 100.00 Using index condition +ANALYZE SELECT id, name FROM t1 WHERE id = 1 OR id = '2'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 2.00 100.00 100.00 Using index condition +ANALYZE SELECT id, name FROM t1 WHERE id = '1' OR id = 2; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 2.00 100.00 100.00 Using index condition +DROP TABLE t1; +# # End of 10.5 tests # # diff --git a/mysql-test/main/func_in.test b/mysql-test/main/func_in.test index e39932a2d50..b88b68f2724 100644 --- a/mysql-test/main/func_in.test +++ b/mysql-test/main/func_in.test @@ -742,6 +742,66 @@ SELECT c1 FROM a WHERE c1 IN ( 1, 9223372036854775807 ); SELECT c1 FROM a WHERE c1 IN ( 1, 9223372036854775808 ); drop table `a`; +--echo # +--echo # MDEV-18319 BIGINT UNSIGNED Performance issue +--echo # + +CREATE OR REPLACE TABLE t1 ( + id bigint(20) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY +); +DELIMITER $$; +FOR i IN 0..255 +DO + INSERT INTO t1 VALUES (); +END FOR +$$ +DELIMITER ;$$ +SELECT MIN(id), MAX(id), COUNT(*) FROM t1; +EXPLAIN SELECT id FROM t1 WHERE id IN (1,2); +EXPLAIN SELECT id FROM t1 WHERE id IN (9223372036854775806, 9223372036854775807); +EXPLAIN SELECT id FROM t1 WHERE id IN (9223372036854775807, 9223372036854775808); +DROP TABLE t1; + + +--echo # +--echo # MDEV-18898 SELECT using wrong index when using operator IN with mixed types +--echo # + +CREATE TEMPORARY TABLE t1 ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + name varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`) +); +DELIMITER $$; +FOR i IN 1..255 +DO + INSERT INTO t1 VALUES (i, MD5(i)); +END FOR +$$ +DELIMITER ;$$ +--echo # +--echo # Constants alone +--echo # +ANALYZE SELECT id, name FROM t1 WHERE id = 1; +ANALYZE SELECT id, name FROM t1 WHERE id = '2'; +--echo # +--echo # Two constants using IN +--echo # +ANALYZE SELECT id, name FROM t1 WHERE id IN (1, 2); +ANALYZE SELECT id, name FROM t1 WHERE id IN ('1', 2) /* Used a wrong index */; +ANALYZE SELECT id, name FROM t1 WHERE id IN (1, '2') /* Used a wrong index */; +ANALYZE SELECT id, name FROM t1 WHERE id IN ('1', '2'); +--echo # +--echo # Two constants using OR +--echo # +ANALYZE SELECT id, name FROM t1 WHERE id = 1 OR id = 2; +ANALYZE SELECT id, name FROM t1 WHERE id = '1' OR id = '2'; +ANALYZE SELECT id, name FROM t1 WHERE id = 1 OR id = '2'; +ANALYZE SELECT id, name FROM t1 WHERE id = '1' OR id = 2; +DROP TABLE t1; + + --echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index 40d99be02f0..13c71515fec 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -1690,6 +1690,13 @@ select json_arrayagg('ä'), json_objectagg(1, 'ä'); json_arrayagg('ä') json_objectagg(1, 'ä') ["ä"] {"1":"ä"} # +# MDEV-31402: SIGSEGV in json_get_path_next | Item_func_json_extract::read_json +# +CREATE TABLE t (id CHAR AS (JSON_COMPACT (JSON_EXTRACT(doc,"$._id"))) UNIQUE KEY,doc JSON,CONSTRAINT notnu CHECK (id IS NOT NULL)); +INSERT INTO t (doc) VALUES ('{ "_id" : { "$oid" : "0ca0b0f0" },"a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" :0} ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] }'); +ERROR 22001: Data too long for column 'id' at row 1 +DROP TABLE t; +# # End of 10.5 tests # # diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test index b7d710e831a..e78a25b3d02 100644 --- a/mysql-test/main/func_json.test +++ b/mysql-test/main/func_json.test @@ -1118,6 +1118,16 @@ set names latin1; select json_arrayagg('ä'), json_objectagg(1, 'ä'); --enable_service_connection +--echo # +--echo # MDEV-31402: SIGSEGV in json_get_path_next | Item_func_json_extract::read_json +--echo # + +CREATE TABLE t (id CHAR AS (JSON_COMPACT (JSON_EXTRACT(doc,"$._id"))) UNIQUE KEY,doc JSON,CONSTRAINT notnu CHECK (id IS NOT NULL)); +--error ER_DATA_TOO_LONG +INSERT INTO t (doc) VALUES ('{ "_id" : { "$oid" : "0ca0b0f0" },"a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" :0} ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] }'); + +DROP TABLE t; + --echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/main/func_time.result b/mysql-test/main/func_time.result index 99c3e1088d0..bf7d974873b 100644 --- a/mysql-test/main/func_time.result +++ b/mysql-test/main/func_time.result @@ -6373,3 +6373,57 @@ NULL SELECT FROM_UNIXTIME(LEAST(3696610869, NULL)); FROM_UNIXTIME(LEAST(3696610869, NULL)) NULL +# +# Start of 10.5 tests +# +# +# MDEV-29149 Assertion `!is_valid_datetime() || fraction_remainder(((item->decimals) < (6) ? (item->decimals) : (6))) == 0' failed in Datetime_truncation_not_needed::Datetime_truncation_not_needed +# +SET @@timestamp= UNIX_TIMESTAMP('2022-07-21 23:00:00'); +SELECT DATE_SUB('2022-07-21 00:00:00', INTERVAL 800 HOUR) AS expected_result; +expected_result +2022-06-17 16:00:00 +SELECT +IF(1,TIMEDIFF('38:59:59','839:00:00'),CAST('2022-12-12' AS DATE)) AS c1, +IF(1,TIMEDIFF('-839:00:00','-38:59:59'),CAST('2022-12-12' AS DATE)) AS c2; +c1 c2 +2022-06-17 16:00:00 2022-06-17 16:00:00 +Warnings: +Warning 1292 Truncated incorrect time value: '839:00:00' +Warning 1292 Truncated incorrect time value: '-839:00:00' +SELECT +IF(1,TIMEDIFF(385959,8390000),CAST('2022-12-12' AS DATE)) AS c1, +IF(1,TIMEDIFF(-8390000,-385959),CAST('2022-12-12' AS DATE)) AS c2; +c1 c2 +2022-06-17 16:00:00 2022-06-17 16:00:00 +Warnings: +Warning 1292 Truncated incorrect time value: '8390000' +Warning 1292 Truncated incorrect time value: '-8390000' +SELECT +TIMEDIFF('38:59:59','839:00:00') AS c1, +CAST(TIMEDIFF('38:59:59','839:00:00') AS TIME(6)) AS c2, +TIMEDIFF('839:00:00','38:59:59') AS c3, +CAST(TIMEDIFF('839:00:00','38:59:59') AS TIME(6)) AS c4; +c1 c2 c3 c4 +-800:00:00 -800:00:00.000000 800:00:00 800:00:00.000000 +Warnings: +Warning 1292 Truncated incorrect time value: '839:00:00' +Warning 1292 Truncated incorrect time value: '839:00:00' +Warning 1292 Truncated incorrect time value: '839:00:00' +Warning 1292 Truncated incorrect time value: '839:00:00' +SELECT +TIMEDIFF(385959,8390000) AS c1, +CAST(TIMEDIFF(385959,8390000) AS TIME(6)) AS c2, +TIMEDIFF(8390000,385959) AS c3, +CAST(TIMEDIFF(8390000,385959) AS TIME(6)) AS c4; +c1 c2 c3 c4 +-800:00:00 -800:00:00.000000 800:00:00 800:00:00.000000 +Warnings: +Warning 1292 Truncated incorrect time value: '8390000' +Warning 1292 Truncated incorrect time value: '8390000' +Warning 1292 Truncated incorrect time value: '8390000' +Warning 1292 Truncated incorrect time value: '8390000' +SET @@timestamp= DEFAULT; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/func_time.test b/mysql-test/main/func_time.test index fb184ab4e16..caf6ec1c6cf 100644 --- a/mysql-test/main/func_time.test +++ b/mysql-test/main/func_time.test @@ -3218,3 +3218,42 @@ SELECT CONCAT(MAKETIME('01', '01', LEAST( -100, NULL ))); --echo # SELECT FROM_UNIXTIME(LEAST(3696610869, NULL)); + + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-29149 Assertion `!is_valid_datetime() || fraction_remainder(((item->decimals) < (6) ? (item->decimals) : (6))) == 0' failed in Datetime_truncation_not_needed::Datetime_truncation_not_needed +--echo # + +SET @@timestamp= UNIX_TIMESTAMP('2022-07-21 23:00:00'); + +SELECT DATE_SUB('2022-07-21 00:00:00', INTERVAL 800 HOUR) AS expected_result; + +SELECT + IF(1,TIMEDIFF('38:59:59','839:00:00'),CAST('2022-12-12' AS DATE)) AS c1, + IF(1,TIMEDIFF('-839:00:00','-38:59:59'),CAST('2022-12-12' AS DATE)) AS c2; + +SELECT + IF(1,TIMEDIFF(385959,8390000),CAST('2022-12-12' AS DATE)) AS c1, + IF(1,TIMEDIFF(-8390000,-385959),CAST('2022-12-12' AS DATE)) AS c2; + +SELECT + TIMEDIFF('38:59:59','839:00:00') AS c1, + CAST(TIMEDIFF('38:59:59','839:00:00') AS TIME(6)) AS c2, + TIMEDIFF('839:00:00','38:59:59') AS c3, + CAST(TIMEDIFF('839:00:00','38:59:59') AS TIME(6)) AS c4; + +SELECT + TIMEDIFF(385959,8390000) AS c1, + CAST(TIMEDIFF(385959,8390000) AS TIME(6)) AS c2, + TIMEDIFF(8390000,385959) AS c3, + CAST(TIMEDIFF(8390000,385959) AS TIME(6)) AS c4; + +SET @@timestamp= DEFAULT; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/gis.result b/mysql-test/main/gis.result index d8d424897fb..8097c7a8ba8 100644 --- a/mysql-test/main/gis.result +++ b/mysql-test/main/gis.result @@ -5072,37 +5072,37 @@ ERROR 42000: Incorrect parameter count in the call to native function 'WITHIN(PO # MDEV-20009 Add CAST(expr AS pluggable_type) # SELECT CAST(1 AS GEOMETRY); -ERROR HY000: Operator does not exists: 'CAST(expr AS geometry)' +ERROR HY000: Operator does not exist: 'CAST(expr AS geometry)' SELECT CAST(1 AS GEOMETRYCOLLECTION); -ERROR HY000: Operator does not exists: 'CAST(expr AS geometrycollection)' +ERROR HY000: Operator does not exist: 'CAST(expr AS geometrycollection)' SELECT CAST(1 AS POINT); -ERROR HY000: Operator does not exists: 'CAST(expr AS point)' +ERROR HY000: Operator does not exist: 'CAST(expr AS point)' SELECT CAST(1 AS LINESTRING); -ERROR HY000: Operator does not exists: 'CAST(expr AS linestring)' +ERROR HY000: Operator does not exist: 'CAST(expr AS linestring)' SELECT CAST(1 AS POLYGON); -ERROR HY000: Operator does not exists: 'CAST(expr AS polygon)' +ERROR HY000: Operator does not exist: 'CAST(expr AS polygon)' SELECT CAST(1 AS MULTIPOINT); -ERROR HY000: Operator does not exists: 'CAST(expr AS multipoint)' +ERROR HY000: Operator does not exist: 'CAST(expr AS multipoint)' SELECT CAST(1 AS MULTILINESTRING); -ERROR HY000: Operator does not exists: 'CAST(expr AS multilinestring)' +ERROR HY000: Operator does not exist: 'CAST(expr AS multilinestring)' SELECT CAST(1 AS MULTIPOLYGON); -ERROR HY000: Operator does not exists: 'CAST(expr AS multipolygon)' +ERROR HY000: Operator does not exist: 'CAST(expr AS multipolygon)' SELECT CONVERT(1, GEOMETRY); -ERROR HY000: Operator does not exists: 'CAST(expr AS geometry)' +ERROR HY000: Operator does not exist: 'CAST(expr AS geometry)' SELECT CONVERT(1, GEOMETRYCOLLECTION); -ERROR HY000: Operator does not exists: 'CAST(expr AS geometrycollection)' +ERROR HY000: Operator does not exist: 'CAST(expr AS geometrycollection)' SELECT CONVERT(1, POINT); -ERROR HY000: Operator does not exists: 'CAST(expr AS point)' +ERROR HY000: Operator does not exist: 'CAST(expr AS point)' SELECT CONVERT(1, LINESTRING); -ERROR HY000: Operator does not exists: 'CAST(expr AS linestring)' +ERROR HY000: Operator does not exist: 'CAST(expr AS linestring)' SELECT CONVERT(1, POLYGON); -ERROR HY000: Operator does not exists: 'CAST(expr AS polygon)' +ERROR HY000: Operator does not exist: 'CAST(expr AS polygon)' SELECT CONVERT(1, MULTIPOINT); -ERROR HY000: Operator does not exists: 'CAST(expr AS multipoint)' +ERROR HY000: Operator does not exist: 'CAST(expr AS multipoint)' SELECT CONVERT(1, MULTILINESTRING); -ERROR HY000: Operator does not exists: 'CAST(expr AS multilinestring)' +ERROR HY000: Operator does not exist: 'CAST(expr AS multilinestring)' SELECT CONVERT(1, MULTIPOLYGON); -ERROR HY000: Operator does not exists: 'CAST(expr AS multipolygon)' +ERROR HY000: Operator does not exist: 'CAST(expr AS multipolygon)' # # MDEV-17832 Protocol: extensions for Pluggable types and JSON, GEOMETRY # diff --git a/mysql-test/main/host_cache_size_functionality.test b/mysql-test/main/host_cache_size_functionality.test index 9ec26010ab6..f37b2ab8c9e 100644 --- a/mysql-test/main/host_cache_size_functionality.test +++ b/mysql-test/main/host_cache_size_functionality.test @@ -43,10 +43,10 @@ select @@global.Host_Cache_Size > 0; --echo # Restart server with Host_Cache_Size 1 let $restart_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect; ---exec echo "wait" > $restart_file +--write_line wait $restart_file --shutdown_server --source include/wait_until_disconnected.inc --- exec echo "restart:--host_cache_size=1 " > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line "restart:--host_cache_size=1 " $MYSQLTEST_VARDIR/tmp/mysqld.1.expect -- enable_reconnect -- source include/wait_until_connected_again.inc @@ -142,10 +142,10 @@ SELECT Host_Cache_Size = @@SESSION.Host_Cache_Size; #--remove_file $MYSQL_TMP_DIR/bind_ip #let $restart_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect; -#--exec echo "wait" > $restart_file +#--write_line wait $restart_file #--shutdown_server #--source include/wait_until_disconnected.inc -#-- exec echo "restart:--bind-address=$bind_ip " > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +#-- write_line "restart:--bind-address=$bind_ip " $MYSQLTEST_VARDIR/tmp/mysqld.1.expect #-- enable_reconnect #-- source include/wait_until_connected_again.inc diff --git a/mysql-test/main/init_file_set_password-7656.test b/mysql-test/main/init_file_set_password-7656.test index 7bca34a0fcf..ac5baa3b04f 100644 --- a/mysql-test/main/init_file_set_password-7656.test +++ b/mysql-test/main/init_file_set_password-7656.test @@ -15,12 +15,12 @@ EOF --enable_reconnect ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --shutdown_server --source include/wait_until_disconnected.inc ---exec echo "restart:--init-file=$MYSQLTEST_VARDIR/init.file " > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line "restart:--init-file=$MYSQLTEST_VARDIR/init.file " $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --source include/wait_until_connected_again.inc select user,host,password,plugin,authentication_string from mysql.user where user='foo'; diff --git a/mysql-test/main/join_cache.result b/mysql-test/main/join_cache.result index b8dddff9296..323c4a73e20 100644 --- a/mysql-test/main/join_cache.result +++ b/mysql-test/main/join_cache.result @@ -6401,5 +6401,27 @@ b b d c c 10 NULL NULL NULL NULL DROP TABLE t1,t2,t3,t4; # +# MDEV-21102: Server crashes in JOIN_CACHE::write_record_data upon EXPLAIN with subqueries and constant tables +# +CREATE TABLE t1 (a int, b int) ENGINE=MyISAM; +CREATE TABLE t2 (c int, d int) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1,10); +CREATE TABLE t3 (e int, key (e)) ENGINE=MyISAM; +INSERT INTO t3 VALUES (2),(3); +# Must not crash, must use join buffer in subquery +EXPLAIN +SELECT * FROM t1 +WHERE a > b OR a IN ( +SELECT c FROM t2 WHERE EXISTS ( +SELECT * FROM t3 t3a JOIN t3 t3b WHERE t3a.e < d +) +); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 1 +3 SUBQUERY t3a range e e 5 NULL 2 Using where; Using index +3 SUBQUERY t3b index NULL e 5 NULL 2 Using index; Using join buffer (flat, BNL join) +DROP TABLE t1,t2,t3; +# # End of 10.4 tests # diff --git a/mysql-test/main/join_cache.test b/mysql-test/main/join_cache.test index be33d116952..4d13a96cb54 100644 --- a/mysql-test/main/join_cache.test +++ b/mysql-test/main/join_cache.test @@ -4304,6 +4304,27 @@ eval $q2; DROP TABLE t1,t2,t3,t4; +--echo # +--echo # MDEV-21102: Server crashes in JOIN_CACHE::write_record_data upon EXPLAIN with subqueries and constant tables +--echo # +CREATE TABLE t1 (a int, b int) ENGINE=MyISAM; + +CREATE TABLE t2 (c int, d int) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1,10); + +CREATE TABLE t3 (e int, key (e)) ENGINE=MyISAM; +INSERT INTO t3 VALUES (2),(3); + +--echo # Must not crash, must use join buffer in subquery +EXPLAIN +SELECT * FROM t1 +WHERE a > b OR a IN ( + SELECT c FROM t2 WHERE EXISTS ( + SELECT * FROM t3 t3a JOIN t3 t3b WHERE t3a.e < d + ) +); +DROP TABLE t1,t2,t3; + --echo # --echo # End of 10.4 tests --echo # diff --git a/mysql-test/main/kill_processlist-6619.result b/mysql-test/main/kill_processlist-6619.result index 25831a1f63b..7dd42790cc7 100644 --- a/mysql-test/main/kill_processlist-6619.result +++ b/mysql-test/main/kill_processlist-6619.result @@ -1,8 +1,4 @@ -SET DEBUG_SYNC='dispatch_command_end SIGNAL ready WAIT_FOR go'; -select 1; connect con1,localhost,root,,; -SET DEBUG_SYNC='now wait_for ready'; -SET DEBUG_SYNC='now signal go'; SHOW PROCESSLIST; Id User Host db Command Time State Info Progress # root # test Sleep # # NULL 0.000 @@ -10,8 +6,6 @@ Id User Host db Command Time State Info Progress SET DEBUG_SYNC='before_execute_sql_command SIGNAL ready WAIT_FOR go'; SHOW PROCESSLIST; connection default; -1 -1 SET DEBUG_SYNC='now WAIT_FOR ready'; KILL QUERY con_id; SET DEBUG_SYNC='now SIGNAL go'; diff --git a/mysql-test/main/kill_processlist-6619.test b/mysql-test/main/kill_processlist-6619.test index 7330c79acd8..0f53034eaa8 100644 --- a/mysql-test/main/kill_processlist-6619.test +++ b/mysql-test/main/kill_processlist-6619.test @@ -4,23 +4,24 @@ --source include/not_embedded.inc --source include/have_debug_sync.inc -# This is to ensure that the following SHOW PROCESSLIST does not show the query -SET DEBUG_SYNC='dispatch_command_end SIGNAL ready WAIT_FOR go'; ---send select 1 +--disable_ps_protocol +# Ensure no lingering connections from an earlier test run, which can very +# rarely still be visible in SHOW PROCESSLIST here. +--let $wait_condition= SELECT COUNT(*) = 1 from information_schema.processlist +--source include/wait_condition.inc --connect (con1,localhost,root,,) -SET DEBUG_SYNC='now wait_for ready'; -SET DEBUG_SYNC='now signal go'; - --let $con_id = `SELECT CONNECTION_ID()` + +let $wait_condition=select command = 'sleep' from information_schema.processlist where id != $con_id; +source include/wait_condition.inc; + --replace_result Execute Query --replace_column 1 # 3 # 6 # 7 # SHOW PROCESSLIST; SET DEBUG_SYNC='before_execute_sql_command SIGNAL ready WAIT_FOR go'; send SHOW PROCESSLIST; --connection default ---reap - # We must wait for the SHOW PROCESSLIST query to have started before sending # the kill. Otherwise, the KILL may be lost since it is reset at the start of # query execution. @@ -34,9 +35,7 @@ reap; SET DEBUG_SYNC='reset'; # Wait until default connection has reset query string -let $wait_condition= - SELECT COUNT(*) = 1 from information_schema.processlist - WHERE info is NULL; +let $wait_condition=select command = 'sleep' from information_schema.processlist where id != $con_id; --source include/wait_condition.inc --replace_result Execute Query diff --git a/mysql-test/main/load_timezones_with_alter_algorithm_inplace.result b/mysql-test/main/load_timezones_with_alter_algorithm_inplace.result new file mode 100644 index 00000000000..4992e7ed93b --- /dev/null +++ b/mysql-test/main/load_timezones_with_alter_algorithm_inplace.result @@ -0,0 +1,18 @@ +set global alter_algorithm=INPLACE; +RENAME TABLE mysql.time_zone TO mysql.time_zone_BACKUP; +RENAME TABLE mysql.time_zone_name TO mysql.time_zone_name_BACKUP; +RENAME TABLE mysql.time_zone_transition TO mysql.time_zone_transition_BACKUP; +RENAME TABLE mysql.time_zone_transition_type TO mysql.time_zone_transition_type_BACKUP; +CREATE TABLE mysql.time_zone LIKE mysql.time_zone_BACKUP; +CREATE TABLE mysql.time_zone_name LIKE mysql.time_zone_name_BACKUP; +CREATE TABLE mysql.time_zone_transition LIKE mysql.time_zone_transition_BACKUP; +CREATE TABLE mysql.time_zone_transition_type LIKE mysql.time_zone_transition_type_BACKUP; +DROP TABLE mysql.time_zone; +DROP TABLE mysql.time_zone_name; +DROP TABLE mysql.time_zone_transition; +DROP TABLE mysql.time_zone_transition_type; +RENAME TABLE mysql.time_zone_BACKUP TO mysql.time_zone; +RENAME TABLE mysql.time_zone_name_BACKUP TO mysql.time_zone_name; +RENAME TABLE mysql.time_zone_transition_BACKUP TO mysql.time_zone_transition; +RENAME TABLE mysql.time_zone_transition_type_BACKUP TO mysql.time_zone_transition_type; +set global alter_algorithm=DEFAULT; diff --git a/mysql-test/main/load_timezones_with_alter_algorithm_inplace.test b/mysql-test/main/load_timezones_with_alter_algorithm_inplace.test new file mode 100644 index 00000000000..809f147fe04 --- /dev/null +++ b/mysql-test/main/load_timezones_with_alter_algorithm_inplace.test @@ -0,0 +1,40 @@ +--source include/not_embedded.inc + +# MDEV-33044 Loading time zones does not work with alter_algorithm INPLACE + +set global alter_algorithm=INPLACE; + +# Because loading timezones alters the mysql tables, +# this test will leave mysql in a different state than when it started. +# Furthermore, checksums on the various mysql.timezone_x tables will fail. + +# Therefore we: +# 1. Make "backups" of the existing tables by renaming them +# 2. Make dummy clones of the tables we just backed up +# 3. Load timezones with alterations made to the dummy clone tables +# 4. Drop the newly made tables with changes made to them +# 5. Restore the backed up tables so the checksums will pass + +RENAME TABLE mysql.time_zone TO mysql.time_zone_BACKUP; +RENAME TABLE mysql.time_zone_name TO mysql.time_zone_name_BACKUP; +RENAME TABLE mysql.time_zone_transition TO mysql.time_zone_transition_BACKUP; +RENAME TABLE mysql.time_zone_transition_type TO mysql.time_zone_transition_type_BACKUP; + +CREATE TABLE mysql.time_zone LIKE mysql.time_zone_BACKUP; +CREATE TABLE mysql.time_zone_name LIKE mysql.time_zone_name_BACKUP; +CREATE TABLE mysql.time_zone_transition LIKE mysql.time_zone_transition_BACKUP; +CREATE TABLE mysql.time_zone_transition_type LIKE mysql.time_zone_transition_type_BACKUP; + +--exec $MYSQL_TZINFO_TO_SQL std_data/zoneinfo | $MYSQL mysql + +DROP TABLE mysql.time_zone; +DROP TABLE mysql.time_zone_name; +DROP TABLE mysql.time_zone_transition; +DROP TABLE mysql.time_zone_transition_type; + +RENAME TABLE mysql.time_zone_BACKUP TO mysql.time_zone; +RENAME TABLE mysql.time_zone_name_BACKUP TO mysql.time_zone_name; +RENAME TABLE mysql.time_zone_transition_BACKUP TO mysql.time_zone_transition; +RENAME TABLE mysql.time_zone_transition_type_BACKUP TO mysql.time_zone_transition_type; + +set global alter_algorithm=DEFAULT; diff --git a/mysql-test/main/log_errchk.test b/mysql-test/main/log_errchk.test index 1afc0e29f3a..c64f6e3c106 100644 --- a/mysql-test/main/log_errchk.test +++ b/mysql-test/main/log_errchk.test @@ -30,12 +30,12 @@ --echo # Case 2: Starting server with fifo file as general log file --echo # and slow query log file. # Restart server with fifo file as general log file. ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --shutdown_server --source include/wait_until_disconnected.inc --enable_reconnect # Write file to make mysql-test-run.pl start up the server again ---exec echo "restart: --general-log-file=$gen_log_file --slow-query-log-file=$slow_query_log_file" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line "restart: --general-log-file=$gen_log_file --slow-query-log-file=$slow_query_log_file" $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --source include/wait_until_connected_again.inc # Error 6 is reported, because the other end is closed diff --git a/mysql-test/main/lowercase_fs_on.test b/mysql-test/main/lowercase_fs_on.test index 1d306826e27..9a7fc369207 100644 --- a/mysql-test/main/lowercase_fs_on.test +++ b/mysql-test/main/lowercase_fs_on.test @@ -16,7 +16,7 @@ let SEARCH_FILE= $MYSQLTEST_VARDIR/log/my_restart.err; --remove_file $SEARCH_FILE #Shutdown the server ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --shutdown_server --source include/wait_until_disconnected.inc @@ -30,7 +30,7 @@ let SEARCH_PATTERN= \[ERROR\] The server option \'lower_case_table_names\' is co --source include/search_pattern_in_file.inc #Restart the server ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --source include/wait_until_connected_again.inc #Cleanup diff --git a/mysql-test/main/mdl_sync.result b/mysql-test/main/mdl_sync.result index 0324c261749..c6b80c50b40 100644 --- a/mysql-test/main/mdl_sync.result +++ b/mysql-test/main/mdl_sync.result @@ -2431,6 +2431,9 @@ create table t1 (a int) engine=myisam; create table t2 (a int) stats_persistent=0, engine=innodb; insert into t1 values (1); insert into t2 values (1); +connect con1, localhost, root; +start transaction with consistent snapshot; +connection default; SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL table_opened WAIT_FOR grlwait execute 2'; update t1,t2 set t1.a=2,t2.a=3; connection con2; @@ -2462,6 +2465,7 @@ connection default; SET DEBUG_SYNC= 'RESET'; drop table t1,t2; disconnect con2; +disconnect con1; # # Bug#50786 Assertion `thd->mdl_context.trans_sentinel() == __null' # failed in open_ltable() diff --git a/mysql-test/main/mdl_sync.test b/mysql-test/main/mdl_sync.test index 7a928a4c9e7..29d95460d16 100644 --- a/mysql-test/main/mdl_sync.test +++ b/mysql-test/main/mdl_sync.test @@ -3115,6 +3115,12 @@ create table t2 (a int) stats_persistent=0, engine=innodb; insert into t1 values (1); insert into t2 values (1); +connect (con1, localhost, root); +# disable innodb purge thread, otherwise it might start purging t2, +# and will take an mdl, affecting metadata_lock_info output. +start transaction with consistent snapshot; +connection default; + SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL table_opened WAIT_FOR grlwait execute 2'; --send update t1,t2 set t1.a=2,t2.a=3 @@ -3160,6 +3166,7 @@ connection default; SET DEBUG_SYNC= 'RESET'; drop table t1,t2; disconnect con2; +disconnect con1; --echo # --echo # Bug#50786 Assertion `thd->mdl_context.trans_sentinel() == __null' diff --git a/mysql-test/main/myisam_crash_before_flush_keys.test b/mysql-test/main/myisam_crash_before_flush_keys.test index 791e43b0c9b..c48f2b42044 100644 --- a/mysql-test/main/myisam_crash_before_flush_keys.test +++ b/mysql-test/main/myisam_crash_before_flush_keys.test @@ -26,14 +26,14 @@ INSERT INTO t1 VALUES (1,2),(2,3),(3,4),(4,5),(5,6); SET SESSION debug_dbug="d,crash_before_flush_keys"; --echo # Write file to make mysql-test-run.pl expect crash ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --echo # Run the crashing query --error 2013 FLUSH TABLE t1; --echo # Write file to make mysql-test-run.pl start the server ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --echo # Turn on reconnect --enable_reconnect diff --git a/mysql-test/main/mysql_client_test.test b/mysql-test/main/mysql_client_test.test index 0de459bd316..d620f4c7078 100644 --- a/mysql-test/main/mysql_client_test.test +++ b/mysql-test/main/mysql_client_test.test @@ -23,7 +23,7 @@ call mtr.add_suppression(" IP address .* could not be resolved"); # server or run mysql-test-run --debug mysql_client_test and check # var/log/mysql_client_test.trace ---exec echo "$MYSQL_CLIENT_TEST" > $MYSQLTEST_VARDIR/log/mysql_client_test.out.log 2>&1 +--write_line "$MYSQL_CLIENT_TEST" $MYSQLTEST_VARDIR/log/mysql_client_test.out.log --exec $MYSQL_CLIENT_TEST --getopt-ll-test=25600M >> $MYSQLTEST_VARDIR/log/mysql_client_test.out.log 2>&1 # End of 4.1 tests diff --git a/mysql-test/main/mysql_client_test_comp.test b/mysql-test/main/mysql_client_test_comp.test index 36a12b6691e..f37d82a20e5 100644 --- a/mysql-test/main/mysql_client_test_comp.test +++ b/mysql-test/main/mysql_client_test_comp.test @@ -12,7 +12,7 @@ SET @old_slow_query_log= @@global.slow_query_log; call mtr.add_suppression(" Error reading file './client_test_db/test_frm_bug.frm'"); call mtr.add_suppression(" IP address .* could not be resolved"); ---exec echo "$MYSQL_CLIENT_TEST" > $MYSQLTEST_VARDIR/log/mysql_client_test_comp.out.log 2>&1 +--write_line "$MYSQL_CLIENT_TEST" $MYSQLTEST_VARDIR/log/mysql_client_test_comp.out.log --exec $MYSQL_CLIENT_TEST --getopt-ll-test=25600M >> $MYSQLTEST_VARDIR/log/mysql_client_test_comp.out.log 2>&1 # End of test diff --git a/mysql-test/main/mysql_client_test_nonblock.test b/mysql-test/main/mysql_client_test_nonblock.test index 73e7a6d378d..c4bc4304307 100644 --- a/mysql-test/main/mysql_client_test_nonblock.test +++ b/mysql-test/main/mysql_client_test_nonblock.test @@ -19,7 +19,7 @@ call mtr.add_suppression(" IP address .* could not be resolved"); # server or run mysql-test-run --debug mysql_client_test and check # var/log/mysql_client_test.trace ---exec echo "$MYSQL_CLIENT_TEST --non-blocking-api" > $MYSQLTEST_VARDIR/log/mysql_client_test.out.log 2>&1 +--write_line "$MYSQL_CLIENT_TEST --non-blocking-api" $MYSQLTEST_VARDIR/log/mysql_client_test.out.log --exec $MYSQL_CLIENT_TEST --non-blocking-api --getopt-ll-test=25600M >> $MYSQLTEST_VARDIR/log/mysql_client_test.out.log 2>&1 # End of 4.1 tests diff --git a/mysql-test/main/mysql_tzinfo_to_sql_symlink.result b/mysql-test/main/mysql_tzinfo_to_sql_symlink.result index 97548768a2d..86ff8179b44 100644 --- a/mysql-test/main/mysql_tzinfo_to_sql_symlink.result +++ b/mysql-test/main/mysql_tzinfo_to_sql_symlink.result @@ -18,6 +18,8 @@ execute immediate if(@wsrep_cannot_replicate_tz, 'select ENGINE into @time_zone_ execute immediate if(@wsrep_cannot_replicate_tz, 'ALTER TABLE time_zone_transition ENGINE=InnoDB', 'do 0'); execute immediate if(@wsrep_cannot_replicate_tz, 'select ENGINE into @time_zone_transition_type_engine from information_schema.TABLES where TABLE_SCHEMA=DATABASE() and TABLE_NAME=''time_zone_transition_type''', 'do 0'); execute immediate if(@wsrep_cannot_replicate_tz, 'ALTER TABLE time_zone_transition_type ENGINE=InnoDB', 'do 0'); +SET @old_alter_alg=@@SESSION.alter_algorithm; +SET session alter_algorithm='COPY'; TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; @@ -52,6 +54,7 @@ execute immediate if(@wsrep_cannot_replicate_tz, concat('ALTER TABLE time_zone E execute immediate if(@wsrep_cannot_replicate_tz, concat('ALTER TABLE time_zone_name ENGINE=', @time_zone_name_engine), 'do 0'); execute immediate if(@wsrep_cannot_replicate_tz, concat('ALTER TABLE time_zone_transition ENGINE=', @time_zone_transition_engine, ', ORDER BY Time_zone_id, Transition_time'), 'do 0'); execute immediate if(@wsrep_cannot_replicate_tz, concat('ALTER TABLE time_zone_transition_type ENGINE=', @time_zone_transition_type_engine, ', ORDER BY Time_zone_id, Transition_type_id'), 'do 0'); +SET session alter_algorithm=@old_alter_alg; # # MDEV-28263: mariadb-tzinfo-to-sql improve wsrep and binlog cases # @@ -67,6 +70,8 @@ execute immediate if(@wsrep_cannot_replicate_tz, 'select ENGINE into @time_zone_ execute immediate if(@wsrep_cannot_replicate_tz, 'ALTER TABLE time_zone_transition ENGINE=InnoDB', 'do 0'); execute immediate if(@wsrep_cannot_replicate_tz, 'select ENGINE into @time_zone_transition_type_engine from information_schema.TABLES where TABLE_SCHEMA=DATABASE() and TABLE_NAME=''time_zone_transition_type''', 'do 0'); execute immediate if(@wsrep_cannot_replicate_tz, 'ALTER TABLE time_zone_transition_type ENGINE=InnoDB', 'do 0'); +SET @old_alter_alg=@@SESSION.alter_algorithm; +SET session alter_algorithm='COPY'; TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; @@ -98,6 +103,7 @@ execute immediate if(@wsrep_cannot_replicate_tz, concat('ALTER TABLE time_zone E execute immediate if(@wsrep_cannot_replicate_tz, concat('ALTER TABLE time_zone_name ENGINE=', @time_zone_name_engine), 'do 0'); execute immediate if(@wsrep_cannot_replicate_tz, concat('ALTER TABLE time_zone_transition ENGINE=', @time_zone_transition_engine, ', ORDER BY Time_zone_id, Transition_time'), 'do 0'); execute immediate if(@wsrep_cannot_replicate_tz, concat('ALTER TABLE time_zone_transition_type ENGINE=', @time_zone_transition_type_engine, ', ORDER BY Time_zone_id, Transition_type_id'), 'do 0'); +SET session alter_algorithm=@old_alter_alg; SELECT COUNT(*) FROM time_zone; COUNT(*) 2 @@ -123,6 +129,8 @@ execute immediate if(@wsrep_is_on, 'SET @save_wsrep_on=@@WSREP_ON, WSREP_ON=OFF' SET @save_sql_log_bin=@@SQL_LOG_BIN; SET SESSION SQL_LOG_BIN=0; SET @wsrep_cannot_replicate_tz=0; +SET @old_alter_alg=@@SESSION.alter_algorithm; +SET session alter_algorithm='COPY'; TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; @@ -152,6 +160,7 @@ execute immediate if(@wsrep_cannot_replicate_tz, 'do 0','ALTER TABLE time_zone_t execute immediate if(@wsrep_cannot_replicate_tz, 'do 0','ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id'); SET SESSION SQL_LOG_BIN=@save_sql_log_bin; execute immediate if(@wsrep_is_on, 'SET SESSION WSREP_ON=@save_wsrep_on', 'do 0'); +SET session alter_algorithm=@old_alter_alg; SELECT COUNT(*) FROM time_zone; COUNT(*) 2 @@ -505,6 +514,8 @@ execute immediate if(@wsrep_cannot_replicate_tz, 'select ENGINE into @time_zone_ execute immediate if(@wsrep_cannot_replicate_tz, 'ALTER TABLE time_zone_transition ENGINE=InnoDB', 'do 0'); execute immediate if(@wsrep_cannot_replicate_tz, 'select ENGINE into @time_zone_transition_type_engine from information_schema.TABLES where TABLE_SCHEMA=DATABASE() and TABLE_NAME=''time_zone_transition_type''', 'do 0'); execute immediate if(@wsrep_cannot_replicate_tz, 'ALTER TABLE time_zone_transition_type ENGINE=InnoDB', 'do 0'); +SET @old_alter_alg=@@SESSION.alter_algorithm; +SET session alter_algorithm='COPY'; TRUNCATE TABLE time_zone; TRUNCATE TABLE time_zone_name; TRUNCATE TABLE time_zone_transition; @@ -522,6 +533,7 @@ execute immediate if(@wsrep_cannot_replicate_tz, concat('ALTER TABLE time_zone E execute immediate if(@wsrep_cannot_replicate_tz, concat('ALTER TABLE time_zone_name ENGINE=', @time_zone_name_engine), 'do 0'); execute immediate if(@wsrep_cannot_replicate_tz, concat('ALTER TABLE time_zone_transition ENGINE=', @time_zone_transition_engine, ', ORDER BY Time_zone_id, Transition_time'), 'do 0'); execute immediate if(@wsrep_cannot_replicate_tz, concat('ALTER TABLE time_zone_transition_type ENGINE=', @time_zone_transition_type_engine, ', ORDER BY Time_zone_id, Transition_type_id'), 'do 0'); +SET session alter_algorithm=@old_alter_alg; DROP TABLE baseline; DROP TABLE time_zone; DROP TABLE time_zone_name; diff --git a/mysql-test/main/mysqld_option_err.result b/mysql-test/main/mysqld_option_err.result index e2c7b0bd213..157edb58532 100644 --- a/mysql-test/main/mysqld_option_err.result +++ b/mysql-test/main/mysqld_option_err.result @@ -4,13 +4,16 @@ Test bad default storage engine. Test non-numeric value passed to number option. Test that bad value for plugin enum option is rejected correctly. Test to see if multiple unknown options will be displayed in the error output -unknown option '--nonexistentoption' -unknown option '--alsononexistent' -unknown variable 'nonexistentvariable=1' +FOUND 1 /unknown option '--nonexistentoption2'/ in mysqltest.log +FOUND 1 /unknown option '--alsononexistent'/ in mysqltest.log +FOUND 1 /unknown variable 'nonexistentvariable=1'/ in mysqltest.log Test to see if multiple ambiguous options and invalid arguments will be displayed in the error output -Error while setting value 'invalid_value' to 'sql_mode' -ambiguous option '--character' (character-set-client-handshake, character_sets_dir) -option '--bootstrap' cannot take an argument +FOUND 1 /Error while setting value 'invalid_value' to 'sql_mode'/ in mysqltest.log +FOUND 1 /ambiguous option '--character'/ in mysqltest.log +FOUND 1 /option '--bootstrap' cannot take an argument/ in mysqltest.log +FOUND 1 /Integer value out of range for uint64: '18446744073709551616' for binlog_cache_size/ in mysqltest.log +FOUND 1 /Unknown suffix 'y' used for variable 'bulk_insert_buffer_size' \(value '123y'\). Legal suffix characters are: K, M, G, T, P, E/ in mysqltest.log +FOUND 1 /Error while setting value '123y' to 'bulk_insert_buffer_size'/ in mysqltest.log Test that --help --verbose works Test that --not-known-option --help --verbose gives error Done. diff --git a/mysql-test/main/mysqld_option_err.test b/mysql-test/main/mysqld_option_err.test index ad4df61b0f8..c2b943bafa1 100644 --- a/mysql-test/main/mysqld_option_err.test +++ b/mysql-test/main/mysqld_option_err.test @@ -25,7 +25,7 @@ mkdir $MYSQLTEST_VARDIR/tmp/mysqld_option_err; --echo Test bad binlog format. ---error 1 +--error 13 --exec $MYSQLD_BOOTSTRAP_CMD --skip-networking --datadir=$MYSQLTEST_VARDIR/tmp/mysqld_option_err --skip-grant-tables --log-bin --binlog-format=badformat >>$MYSQLTEST_VARDIR/tmp/mysqld_option_err/mysqltest.log 2>&1 @@ -35,7 +35,7 @@ mkdir $MYSQLTEST_VARDIR/tmp/mysqld_option_err; --echo Test non-numeric value passed to number option. ---error 1 +--error 9 --exec $MYSQLD_BOOTSTRAP_CMD --skip-networking --datadir=$MYSQLTEST_VARDIR/tmp/mysqld_option_err --skip-grant-tables --min-examined-row-limit=notanumber >>$MYSQLTEST_VARDIR/tmp/mysqld_option_err/mysqltest.log 2>&1 @@ -46,17 +46,35 @@ mkdir $MYSQLTEST_VARDIR/tmp/mysqld_option_err; --error 7 --exec $MYSQLD_BOOTSTRAP_CMD --skip-networking --datadir=$MYSQLTEST_VARDIR/tmp/mysqld_option_err --skip-grant-tables --plugin-dir=$MYSQLTEST_VARDIR/plugins --plugin-load=example=ha_example.so --plugin-example-enum-var=noexist >>$MYSQLTEST_VARDIR/tmp/mysqld_option_err/mysqltest.log 2>&1 +--let SEARCH_FILE = $MYSQLTEST_VARDIR/tmp/mysqld_option_err/mysqltest.log + --echo Test to see if multiple unknown options will be displayed in the error output -# Remove the noise to make the test robust ---replace_regex /^((?!nonexistent).)*$// /.*unknown/unknown/ --error 7 ---exec $MYSQLD_BOOTSTRAP_CMD --skip-networking --datadir=$MYSQLTEST_VARDIR/tmp/mysqld_option_err --skip-grant-tables --nonexistentoption --alsononexistent --nonexistentvariable=1 2>&1 +--exec $MYSQLD_BOOTSTRAP_CMD --skip-networking --datadir=$MYSQLTEST_VARDIR/tmp/mysqld_option_err --skip-grant-tables --nonexistentoption2 --alsononexistent --nonexistentvariable=1 >>$MYSQLTEST_VARDIR/tmp/mysqld_option_err/mysqltest.log 2>&1 + +--let SEARCH_PATTERN=unknown option '--nonexistentoption2' +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN=unknown option '--alsononexistent' +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN=unknown variable 'nonexistentvariable=1' +--source include/search_pattern_in_file.inc --echo Test to see if multiple ambiguous options and invalid arguments will be displayed in the error output -# Remove the noise to make the test robust ---replace_regex /^((?!('sql_mode'|'--character'|'--bootstrap')).)*$// /.*Error while setting value/Error while setting value/ /.*ambiguous option/ambiguous option/ /.*option '--bootstrap'/option '--bootstrap'/ ---error 1 ---exec $MYSQLD_BOOTSTRAP_CMD --skip-networking --datadir=$MYSQLTEST_VARDIR/tmp/mysqld_option_err --skip-grant-tables --getopt-prefix-matching --sql-mode=invalid_value --character --bootstrap=partstoob 2>&1 +--error 9 +--exec $MYSQLD_BOOTSTRAP_CMD --skip-networking --datadir=$MYSQLTEST_VARDIR/tmp/mysqld_option_err --skip-grant-tables --getopt-prefix-matching --sql-mode=invalid_value --character --bootstrap=partstoob --binlog_cache_size=18446744073709551616 --bulk_insert_buffer_size=123y >>$MYSQLTEST_VARDIR/tmp/mysqld_option_err/mysqltest.log 2>&1 + +--let SEARCH_PATTERN=Error while setting value 'invalid_value' to 'sql_mode' +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN=ambiguous option '--character' +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN=option '--bootstrap' cannot take an argument +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN=Integer value out of range for uint64: '18446744073709551616' for binlog_cache_size +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN=Unknown suffix 'y' used for variable 'bulk_insert_buffer_size' \(value '123y'\). Legal suffix characters are: K, M, G, T, P, E +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN=Error while setting value '123y' to 'bulk_insert_buffer_size' +--source include/search_pattern_in_file.inc # # Test that an wrong option with --help --verbose gives an error diff --git a/mysql-test/main/openssl_1.test b/mysql-test/main/openssl_1.test index 9232868bddd..24525287ea0 100644 --- a/mysql-test/main/openssl_1.test +++ b/mysql-test/main/openssl_1.test @@ -68,7 +68,7 @@ drop table t1; # Test that we can't open connection to server if we are using # a different cacert # ---exec echo "this query should not execute;" > $MYSQLTEST_VARDIR/tmp/test.sql +--write_line "this query should not execute;" $MYSQLTEST_VARDIR/tmp/test.sql # Handle that openssl gives different error messages from YaSSL. --replace_regex /2026 TLS\/SSL error.*/2026 TLS\/SSL error: xxxx/ --error 1 diff --git a/mysql-test/main/plugin_loaderr.test b/mysql-test/main/plugin_loaderr.test index 85621ad047d..1623630bb81 100644 --- a/mysql-test/main/plugin_loaderr.test +++ b/mysql-test/main/plugin_loaderr.test @@ -13,14 +13,14 @@ FROM INFORMATION_SCHEMA.PLUGINS WHERE plugin_name = 'innodb'; --echo # --echo # MDEV-6351 --plugin=force has no effect for built-in plugins --echo # ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --shutdown_server --source include/wait_until_disconnected.inc --error 1 --exec $MYSQLD_CMD --innodb=force --innodb-page-size=6000 --disable-log-error ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --enable_reconnect --source include/wait_until_connected_again.inc --disable_reconnect diff --git a/mysql-test/main/ps.result b/mysql-test/main/ps.result index 198e328e626..fb3681ca944 100644 --- a/mysql-test/main/ps.result +++ b/mysql-test/main/ps.result @@ -5979,6 +5979,19 @@ EXECUTE stmt USING DEFAULT; # Clean up DEALLOCATE PREPARE stmt; DROP TABLE t1, t2; +# MDEV-33218: Assertion `active_arena->is_stmt_prepare_or_first_stmt_execute() || active_arena->state == Query_arena::STMT_SP_QUERY_ARGUMENTS' failed. in st_select_lex::fix_prepare_information +CREATE TABLE t1 AS SELECT 1 f; +PREPARE stmt FROM 'SHOW CREATE TABLE t1'; +DROP TABLE t1; +EXECUTE stmt; +ERROR 42S02: Table 'test.t1' doesn't exist +CREATE VIEW t1 AS SELECT 1; +EXECUTE stmt; +View Create View character_set_client collation_connection +t1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `t1` AS select 1 AS `1` latin1 latin1_swedish_ci +# Clean up +DEALLOCATE PREPARE stmt; +DROP VIEW t1; # # End of 10.4 tests # diff --git a/mysql-test/main/ps.test b/mysql-test/main/ps.test index a360d0efd0f..c7568f73beb 100644 --- a/mysql-test/main/ps.test +++ b/mysql-test/main/ps.test @@ -5421,6 +5421,18 @@ EXECUTE stmt USING DEFAULT; DEALLOCATE PREPARE stmt; DROP TABLE t1, t2; +--echo # MDEV-33218: Assertion `active_arena->is_stmt_prepare_or_first_stmt_execute() || active_arena->state == Query_arena::STMT_SP_QUERY_ARGUMENTS' failed. in st_select_lex::fix_prepare_information +CREATE TABLE t1 AS SELECT 1 f; +PREPARE stmt FROM 'SHOW CREATE TABLE t1'; +DROP TABLE t1; +--error ER_NO_SUCH_TABLE +EXECUTE stmt; +CREATE VIEW t1 AS SELECT 1; +EXECUTE stmt; +--echo # Clean up +DEALLOCATE PREPARE stmt; +DROP VIEW t1; + --echo # --echo # End of 10.4 tests --echo # diff --git a/mysql-test/main/query_cache.result b/mysql-test/main/query_cache.result index f78a6ccc388..f68f619fed0 100644 --- a/mysql-test/main/query_cache.result +++ b/mysql-test/main/query_cache.result @@ -2208,12 +2208,42 @@ Qcache_queries_in_cache 0 DROP FUNCTION foo; drop table t1; # +# MDEV-33861: main.query_cache fails with embedded after +# enabling WITH_PROTECT_STATEMENT_MEMROOT +# +create table t1 (s1 int); +create procedure f3 () begin +select * from t1; +end; +// +create procedure f4 () begin +select * from t1; +end; +// +Call f4(); +s1 +cAll f3(); +s1 +insert into t1 values (2); +caLl f3(); +s1 +2 +drop procedure f3; +drop procedure f4; +drop table t1; +# +# End of 10.4 tests +# +# # MDEV-24858 SIGABRT in DbugExit from my_malloc in Query_cache::init_cache Regression # SET @qc= @@query_cache_size; set global Query_cache_size=18446744073709547520; SET GLOBAL query_cache_size= @qc; # +# End of 10.5 tests +# +# # MDEV-22301 JSON_TABLE: Queries are not inserted into query cache. # create table t1 (a text); @@ -2239,6 +2269,7 @@ DROP TABLE t; restore defaults SET GLOBAL query_cache_type= default; SET GLOBAL query_cache_size=@save_query_cache_size; +# End of 10.6 tests # # MDEV-29028: Queries using RANDOM_BYTES get stored in query cache # @@ -2261,6 +2292,4 @@ improbable 0 drop table t1; set global query_cache_type= @qcache; -# # End of 10.10 tests -# diff --git a/mysql-test/main/query_cache.test b/mysql-test/main/query_cache.test index 08756b80697..feb9ecf526c 100644 --- a/mysql-test/main/query_cache.test +++ b/mysql-test/main/query_cache.test @@ -1807,6 +1807,40 @@ show status like "Qcache_queries_in_cache"; DROP FUNCTION foo; drop table t1; +--echo # +--echo # MDEV-33861: main.query_cache fails with embedded after +--echo # enabling WITH_PROTECT_STATEMENT_MEMROOT +--echo # + +create table t1 (s1 int); +--delimiter // +create procedure f3 () begin +select * from t1; +end; +// +create procedure f4 () begin +select * from t1; +end; +// +--delimiter ; + +Call f4(); + +cAll f3(); + +insert into t1 values (2); + +caLl f3(); + +drop procedure f3; +drop procedure f4; +drop table t1; + + +--echo # +--echo # End of 10.4 tests +--echo # + --echo # --echo # MDEV-24858 SIGABRT in DbugExit from my_malloc in Query_cache::init_cache Regression --echo # @@ -1816,6 +1850,10 @@ set global Query_cache_size=18446744073709547520; SET GLOBAL query_cache_size= @qc; --enable_warnings +--echo # +--echo # End of 10.5 tests +--echo # + --echo # --echo # MDEV-22301 JSON_TABLE: Queries are not inserted into query cache. --echo # @@ -1838,6 +1876,8 @@ DROP TABLE t; SET GLOBAL query_cache_type= default; SET GLOBAL query_cache_size=@save_query_cache_size; +--echo # End of 10.6 tests + --echo # --echo # MDEV-29028: Queries using RANDOM_BYTES get stored in query cache --echo # @@ -1866,7 +1906,6 @@ select random_bytes(1024) = random_bytes(1024) as improbable; drop table t1; set global query_cache_type= @qcache; ---echo # --echo # End of 10.10 tests ---echo # + --enable_ps2_protocol diff --git a/mysql-test/main/read_only_innodb.result b/mysql-test/main/read_only_innodb.result index cfc8f2ecb17..85aee64087f 100644 --- a/mysql-test/main/read_only_innodb.result +++ b/mysql-test/main/read_only_innodb.result @@ -70,7 +70,7 @@ UNLOCK TABLES; DROP TABLE t1; DROP USER test@localhost; disconnect con1; -echo End of 5.1 tests +# End of 5.1 tests # # Bug#33669: Transactional temporary tables do not work under --read-only # @@ -244,3 +244,26 @@ connection default; SET GLOBAL READ_ONLY = OFF; DROP USER bug33669@localhost; DROP DATABASE db1; +# End of 5.5 tests +# +# MDEV-33889 Read only server throws error when running a create temporary table as select statement +# +create table t1(a int) engine=innodb; +create user u1@localhost; +grant insert, select, update, delete, create temporary tables on test.* to u1@localhost; +insert into t1 values (1); +set global read_only=1; +connect u1,localhost,u1; +set default_tmp_storage_engine=innodb; +create temporary table tt1 (a int); +create temporary table tt2 like t1; +create temporary table tt3 as select * from t1; +select * from tt3; +a +1 +disconnect u1; +connection default; +drop table t1; +drop user u1@localhost; +set global read_only=0; +# End of 10.5 tests diff --git a/mysql-test/main/read_only_innodb.test b/mysql-test/main/read_only_innodb.test index e2c2979c393..59af952da8d 100644 --- a/mysql-test/main/read_only_innodb.test +++ b/mysql-test/main/read_only_innodb.test @@ -103,7 +103,7 @@ DROP USER test@localhost; disconnect con1; ---echo echo End of 5.1 tests +--echo # End of 5.1 tests --echo # --echo # Bug#33669: Transactional temporary tables do not work under --read-only @@ -250,3 +250,29 @@ SET GLOBAL READ_ONLY = OFF; DROP USER bug33669@localhost; DROP DATABASE db1; +--echo # End of 5.5 tests + +--echo # +--echo # MDEV-33889 Read only server throws error when running a create temporary table as select statement +--echo # +create table t1(a int) engine=innodb; +create user u1@localhost; +grant insert, select, update, delete, create temporary tables on test.* to u1@localhost; +insert into t1 values (1); +set global read_only=1; + +connect u1,localhost,u1; +set default_tmp_storage_engine=innodb; + +create temporary table tt1 (a int); +create temporary table tt2 like t1; +create temporary table tt3 as select * from t1; +select * from tt3; +disconnect u1; + +connection default; +drop table t1; +drop user u1@localhost; +set global read_only=0; + +--echo # End of 10.5 tests diff --git a/mysql-test/main/rowid_filter_innodb.result b/mysql-test/main/rowid_filter_innodb.result index db52e4dc458..85a3008c1a6 100644 --- a/mysql-test/main/rowid_filter_innodb.result +++ b/mysql-test/main/rowid_filter_innodb.result @@ -4170,5 +4170,105 @@ Warnings: Note 1276 Field or reference 'test.t1.pk' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`c1` AS `c1` from `test`.`t1` where !<`test`.`t1`.`c1`,`test`.`t1`.`pk`>((`test`.`t1`.`c1`,(/* select#2 */ select `test`.`t2`.`c1` from `test`.`t2` join `test`.`t1` `a1` where `test`.`t2`.`i1` = `test`.`t1`.`pk` and `test`.`t2`.`i1` between 3 and 5 and trigcond((`test`.`t1`.`c1`) = `test`.`t2`.`c1`)))) DROP TABLE t1,t2; -set global innodb_stats_persistent= @stats.save; +# +# MDEV-31154: Fatal InnoDB error or assertion `!is_v' failure upon multi-update with indexed virtual column +# +# Test with auto generated Primary Key +# +SET @save_optimizer_switch= @@optimizer_switch; +SET optimizer_switch='rowid_filter=on'; +CREATE TABLE t0(a int); +INSERT INTO t0 SELECT seq FROM seq_1_to_20; +ANALYZE TABLE t0 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t0 analyze status Engine-independent statistics collected +test.t0 analyze status OK +CREATE TABLE t1 ( +a int, +b int as (a * 2) VIRTUAL, +f char(200), /* Filler */ +key (b), +key (a) +) engine=innodb; +INSERT INTO t1 (a, f) SELECT seq, seq FROM seq_1_to_1000; +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 +# Test for type 'ref|filter' +EXPLAIN SELECT count(*) from t0,t1 WHERE t0.a=t1.b AND t1.a<20; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t0 ALL NULL NULL NULL NULL 20 Using where +1 SIMPLE t1 ref|filter b,a b|a 5|5 test.t0.a 1 (2%) Using where; Using rowid filter +SELECT count(*) from t0,t1 WHERE t0.a=t1.b AND t1.a<20; +count(*) +10 +EXPLAIN SELECT count(*) from t0,t1 WHERE t0.a=t1.b AND t1.a<20 FOR UPDATE; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t0 ALL NULL NULL NULL NULL 20 Using where +1 SIMPLE t1 ref|filter b,a b|a 5|5 test.t0.a 1 (2%) Using where; Using rowid filter +SELECT count(*) from t0,t1 WHERE t0.a=t1.b AND t1.a<20 FOR UPDATE; +count(*) +10 +# Test for type 'range|filter' +EXPLAIN SELECT count(*) FROM t1 WHERE a<100 and b <100; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range|filter b,a b|a 5|5 NULL 49 (10%) Using where; Using rowid filter +SELECT count(*) FROM t1 WHERE a<100 and b <100; +count(*) +49 +EXPLAIN SELECT count(*) FROM t1 WHERE a<100 and b <100 FOR UPDATE; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range|filter b,a b|a 5|5 NULL 49 (10%) Using where; Using rowid filter +SELECT count(*) FROM t1 WHERE a<100 and b <100 FOR UPDATE; +count(*) +49 +# Test with Primary Key +# +DROP TABLE t1; +CREATE TABLE t1 ( +p int PRIMARY KEY AUTO_INCREMENT, +a int, +b int as (a * 2) VIRTUAL, +f char(200), /* Filler */ +key (b), +key (a) +) engine=innodb; +INSERT INTO t1 (a, f) SELECT seq, seq FROM seq_1_to_1000; +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 +# Test for type 'ref|filter' +EXPLAIN SELECT count(*) from t0,t1 WHERE t0.a=t1.b AND t1.a<20; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t0 ALL NULL NULL NULL NULL 20 Using where +1 SIMPLE t1 ref|filter b,a b|a 5|5 test.t0.a 1 (2%) Using where; Using rowid filter +SELECT count(*) from t0,t1 WHERE t0.a=t1.b AND t1.a<20; +count(*) +10 +EXPLAIN SELECT count(*) from t0,t1 WHERE t0.a=t1.b AND t1.a<20 FOR UPDATE; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t0 ALL NULL NULL NULL NULL 20 Using where +1 SIMPLE t1 ref|filter b,a b|a 5|5 test.t0.a 1 (2%) Using where; Using rowid filter +SELECT count(*) from t0,t1 WHERE t0.a=t1.b AND t1.a<20 FOR UPDATE; +count(*) +10 +# Test for type 'range|filter' +EXPLAIN SELECT count(*) FROM t1 WHERE a<100 and b <100; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range|filter b,a b|a 5|5 NULL 49 (10%) Using where; Using rowid filter +SELECT count(*) FROM t1 WHERE a<100 and b <100; +count(*) +49 +EXPLAIN SELECT count(*) FROM t1 WHERE a<100 and b <100 FOR UPDATE; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range|filter b,a b|a 5|5 NULL 49 (10%) Using where; Using rowid filter +SELECT count(*) FROM t1 WHERE a<100 and b <100 FOR UPDATE; +count(*) +49 +SET optimizer_switch=@save_optimizer_switch; +DROP TABLE t0, t1; # End of 10.4 tests +# End of 10.6 tests +set global innodb_stats_persistent= @stats.save; diff --git a/mysql-test/main/rowid_filter_innodb.test b/mysql-test/main/rowid_filter_innodb.test index 6777baf8322..b0d65837127 100644 --- a/mysql-test/main/rowid_filter_innodb.test +++ b/mysql-test/main/rowid_filter_innodb.test @@ -1,6 +1,8 @@ --source include/no_valgrind_without_big.inc --source include/have_innodb.inc --source include/have_debug.inc +--source include/have_sequence.inc +--source include/innodb_stable_estimates.inc SET SESSION DEFAULT_STORAGE_ENGINE='InnoDB'; @@ -683,6 +685,82 @@ eval EXPLAIN EXTENDED $q; DROP TABLE t1,t2; -set global innodb_stats_persistent= @stats.save; +--echo # +--echo # MDEV-31154: Fatal InnoDB error or assertion `!is_v' failure upon multi-update with indexed virtual column +--echo # + +--echo # Test with auto generated Primary Key +--echo # + +SET @save_optimizer_switch= @@optimizer_switch; +SET optimizer_switch='rowid_filter=on'; + +CREATE TABLE t0(a int); +INSERT INTO t0 SELECT seq FROM seq_1_to_20; +ANALYZE TABLE t0 PERSISTENT FOR ALL; + +CREATE TABLE t1 ( + a int, + b int as (a * 2) VIRTUAL, + f char(200), /* Filler */ + key (b), + key (a) +) engine=innodb; + +INSERT INTO t1 (a, f) SELECT seq, seq FROM seq_1_to_1000; +ANALYZE TABLE t1 PERSISTENT FOR ALL; + +--echo # Test for type 'ref|filter' +EXPLAIN SELECT count(*) from t0,t1 WHERE t0.a=t1.b AND t1.a<20; +SELECT count(*) from t0,t1 WHERE t0.a=t1.b AND t1.a<20; + +EXPLAIN SELECT count(*) from t0,t1 WHERE t0.a=t1.b AND t1.a<20 FOR UPDATE; +SELECT count(*) from t0,t1 WHERE t0.a=t1.b AND t1.a<20 FOR UPDATE; + +--echo # Test for type 'range|filter' +EXPLAIN SELECT count(*) FROM t1 WHERE a<100 and b <100; +SELECT count(*) FROM t1 WHERE a<100 and b <100; + +EXPLAIN SELECT count(*) FROM t1 WHERE a<100 and b <100 FOR UPDATE; +SELECT count(*) FROM t1 WHERE a<100 and b <100 FOR UPDATE; + +--echo # Test with Primary Key +--echo # + +DROP TABLE t1; +CREATE TABLE t1 ( + p int PRIMARY KEY AUTO_INCREMENT, + a int, + b int as (a * 2) VIRTUAL, + f char(200), /* Filler */ + key (b), + key (a) +) engine=innodb; + +INSERT INTO t1 (a, f) SELECT seq, seq FROM seq_1_to_1000; +ANALYZE TABLE t1 PERSISTENT FOR ALL; + +--echo # Test for type 'ref|filter' +EXPLAIN SELECT count(*) from t0,t1 WHERE t0.a=t1.b AND t1.a<20; +SELECT count(*) from t0,t1 WHERE t0.a=t1.b AND t1.a<20; + +EXPLAIN SELECT count(*) from t0,t1 WHERE t0.a=t1.b AND t1.a<20 FOR UPDATE; +SELECT count(*) from t0,t1 WHERE t0.a=t1.b AND t1.a<20 FOR UPDATE; + +--echo # Test for type 'range|filter' +EXPLAIN SELECT count(*) FROM t1 WHERE a<100 and b <100; +SELECT count(*) FROM t1 WHERE a<100 and b <100; + +EXPLAIN SELECT count(*) FROM t1 WHERE a<100 and b <100 FOR UPDATE; +SELECT count(*) FROM t1 WHERE a<100 and b <100 FOR UPDATE; + +SET optimizer_switch=@save_optimizer_switch; + +DROP TABLE t0, t1; --echo # End of 10.4 tests + +--echo # End of 10.6 tests + +set global innodb_stats_persistent= @stats.save; + diff --git a/mysql-test/main/shutdown.test b/mysql-test/main/shutdown.test index 71f2156a17f..b26a6d4b6f6 100644 --- a/mysql-test/main/shutdown.test +++ b/mysql-test/main/shutdown.test @@ -20,13 +20,13 @@ drop procedure try_shutdown; --let $_expect_file_name= `select regexp_replace(@@tmpdir, '^.*/','')` --let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/$_expect_file_name.expect ---exec echo "wait" > $_expect_file_name +--write_line wait $_expect_file_name --send shutdown --connection default --source include/wait_until_disconnected.inc ---exec echo "restart" > $_expect_file_name +--write_line restart $_expect_file_name --enable_reconnect --source include/wait_until_connected_again.inc diff --git a/mysql-test/main/skip_grants.test b/mysql-test/main/skip_grants.test index b74cd41b039..5af697f614a 100644 --- a/mysql-test/main/skip_grants.test +++ b/mysql-test/main/skip_grants.test @@ -176,12 +176,12 @@ drop user baz@baz; SELECT @@skip_grant_tables AS EXPECT_1; # Also check when the server starts without "--skip-grant-table" option ---let $restart_parameters = "--skip-skip-grant-tables" +--let $restart_parameters = --skip-skip-grant-tables --source include/restart_mysqld.inc SELECT @@skip_grant_tables AS EXPECT_0; # Need to restart the server to restore the "--skip-grant-tables" state ---let $restart_parameters = "--skip-grant-tables" +--let $restart_parameters = --skip-grant-tables --source include/restart_mysqld.inc --echo # diff --git a/mysql-test/main/sp.result b/mysql-test/main/sp.result index 522c2ced9bf..71268c5d051 100644 --- a/mysql-test/main/sp.result +++ b/mysql-test/main/sp.result @@ -7179,15 +7179,14 @@ CREATE VIEW t1 AS SELECT 10 AS f1; CALL p1(1); ERROR HY000: The target table t1 of the INSERT is not insertable-into CREATE TEMPORARY TABLE t1 (f1 INT); -# t1 still refers to the view since it was inlined CALL p1(2); -ERROR HY000: The target table t1 of the INSERT is not insertable-into DROP VIEW t1; # t1 now refers to the temporary table CALL p1(3); # Check which values were inserted into the temp table. SELECT * FROM t1; f1 +2 3 DROP TEMPORARY TABLE t1; DROP PROCEDURE p1; diff --git a/mysql-test/main/sp.test b/mysql-test/main/sp.test index 4e9b4c78881..2bc71bd1db6 100644 --- a/mysql-test/main/sp.test +++ b/mysql-test/main/sp.test @@ -8632,8 +8632,6 @@ CALL p1(1); CREATE TEMPORARY TABLE t1 (f1 INT); ---echo # t1 still refers to the view since it was inlined ---error ER_NON_INSERTABLE_TABLE CALL p1(2); DROP VIEW t1; diff --git a/mysql-test/main/ssl_crl.result b/mysql-test/main/ssl_crl.result index d5603254ea5..58e3e07f746 100644 --- a/mysql-test/main/ssl_crl.result +++ b/mysql-test/main/ssl_crl.result @@ -2,4 +2,4 @@ Variable_name Value Ssl_version TLS_VERSION # try logging in with a certificate in the server's --ssl-crl : should fail -ERROR 2026 (HY000): TLS/SSL error: sslv3 alert certificate revoked +ERROR 2026 (HY000): TLS/SSL error: ssl/tls alert certificate revoked diff --git a/mysql-test/main/ssl_crl.test b/mysql-test/main/ssl_crl.test index 9b4758578a7..a09490f2b9b 100644 --- a/mysql-test/main/ssl_crl.test +++ b/mysql-test/main/ssl_crl.test @@ -7,7 +7,7 @@ --exec $MYSQL --ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem --ssl-key=$MYSQL_TEST_DIR/std_data/server-new-key.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/server-new-cert.pem test -e "SHOW STATUS LIKE 'Ssl_version'" --echo # try logging in with a certificate in the server's --ssl-crl : should fail -# OpenSSL 1.1.1a correctly rejects the certificate, but the error message is different ---replace_regex /ERROR 2013 \(HY000\): Lost connection to server at '.*', system error: [0-9]+/ERROR 2026 (HY000): TLS\/SSL error: sslv3 alert certificate revoked/ +# OpenSSL 1.1.1a and later releases correctly rejects the certificate, but the error message is different +--replace_regex /(ERROR 2013 \(HY000\): Lost connection to server at '.*', system error: [0-9]+|ERROR 2026 \(HY000\): TLS\/SSL error: sslv3 alert certificate revoked)/ERROR 2026 (HY000): TLS\/SSL error: ssl\/tls alert certificate revoked/ --error 1 --exec $MYSQL --ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem test -e "SHOW STATUS LIKE 'Ssl_version'" 2>&1 diff --git a/mysql-test/main/ssl_timeout.result b/mysql-test/main/ssl_timeout.result index 208be527a6b..d94cfed8571 100644 --- a/mysql-test/main/ssl_timeout.result +++ b/mysql-test/main/ssl_timeout.result @@ -1,5 +1,5 @@ # connect with read timeout so SLEEP() should timeout -connect ssl_con,localhost,root,,,,,SSL read_timeout=5; +connect ssl_con,localhost,root,,,,,SSL read_timeout=5$_timeout_adjustment; # Check ssl turned on SELECT (VARIABLE_VALUE <> '') AS have_ssl FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME='Ssl_cipher'; have_ssl diff --git a/mysql-test/main/ssl_timeout.test b/mysql-test/main/ssl_timeout.test index f5965f874ff..d762ebc35a9 100644 --- a/mysql-test/main/ssl_timeout.test +++ b/mysql-test/main/ssl_timeout.test @@ -1,10 +1,11 @@ --source include/have_ssl_communication.inc +--source include/slow_environ.inc # Save the initial number of concurrent sessions --source include/count_sessions.inc --echo # connect with read timeout so SLEEP() should timeout -connect (ssl_con,localhost,root,,,,,SSL read_timeout=5); +connect (ssl_con,localhost,root,,,,,SSL read_timeout=5$_timeout_adjustment); --echo # Check ssl turned on SELECT (VARIABLE_VALUE <> '') AS have_ssl FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME='Ssl_cipher'; diff --git a/mysql-test/main/subselect4.result b/mysql-test/main/subselect4.result index 6d1e0dac1cc..f08dacf51cf 100644 --- a/mysql-test/main/subselect4.result +++ b/mysql-test/main/subselect4.result @@ -3330,4 +3330,33 @@ a 2 DEALLOCATE PREPARE stmt; DROP TABLE t1,t2,t3; +# +# MDEV-33747: Optimization of (SELECT) IN (SELECT ...) executes subquery at prepare stage +# +create table t1 (a int, b int); +insert into t1 select seq, seq from seq_1_to_200; +create table t2 as select * from t1; +create table t3 as select * from t1; +analyze table t1,t2,t3; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK +test.t3 analyze status Engine-independent statistics collected +test.t3 analyze status OK +select @@expensive_subquery_limit < 200 as DEFAULTS_ARE_SUITABLE; +DEFAULTS_ARE_SUITABLE +1 +flush status; +explain select * from t1 where a<3 or (select max(a) from t2) in (select b from t3); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 200 Using where +3 SUBQUERY t3 ALL NULL NULL NULL NULL 200 Using where +2 SUBQUERY t2 ALL NULL NULL NULL NULL 200 +# Must show 0. If this shows 200, this means subquery was executed and you have a bug: +show status like 'Handler_read_rnd_next%'; +Variable_name Value +Handler_read_rnd_next 0 +drop table t1,t2,t3; # End of 10.4 tests diff --git a/mysql-test/main/subselect4.test b/mysql-test/main/subselect4.test index 41fa9066764..854b37363af 100644 --- a/mysql-test/main/subselect4.test +++ b/mysql-test/main/subselect4.test @@ -2670,5 +2670,20 @@ DEALLOCATE PREPARE stmt; DROP TABLE t1,t2,t3; +--echo # +--echo # MDEV-33747: Optimization of (SELECT) IN (SELECT ...) executes subquery at prepare stage +--echo # +create table t1 (a int, b int); +insert into t1 select seq, seq from seq_1_to_200; +create table t2 as select * from t1; +create table t3 as select * from t1; +analyze table t1,t2,t3; +select @@expensive_subquery_limit < 200 as DEFAULTS_ARE_SUITABLE; +flush status; +explain select * from t1 where a<3 or (select max(a) from t2) in (select b from t3); +--echo # Must show 0. If this shows 200, this means subquery was executed and you have a bug: +show status like 'Handler_read_rnd_next%'; +drop table t1,t2,t3; + --echo # End of 10.4 tests diff --git a/mysql-test/main/temp_table.result b/mysql-test/main/temp_table.result index 23052e03a43..61b78f96d4f 100644 --- a/mysql-test/main/temp_table.result +++ b/mysql-test/main/temp_table.result @@ -614,6 +614,55 @@ Tables_in_test # in 11.2 and above here should be listed above used temporary tables DROP TEMPORARY TABLE t1, t2; # +# MDEV-33218: Assertion `active_arena->is_stmt_prepare_or_first_stmt_execute() || active_arena->state == Query_arena::STMT_SP_QUERY_ARGUMENTS' failed. in st_select_lex::fix_prepare_information +# +CREATE VIEW v1 AS SELECT 5; +CREATE PROCEDURE sp() SELECT * FROM v1; +CREATE TEMPORARY TABLE v1 as SELECT 7; +# sp() accesses the temporary table v1 that hides the view with the same name +# Therefore expected output is the row (7) +CALL sp(); +7 +7 +DROP TEMPORARY TABLE v1; +# After the temporary table v1 has been dropped the next invocation of sp() +# accesses the view v1. So, expected output is the row (5) +CALL sp(); +5 +5 +# Clean up +DROP VIEW v1; +DROP PROCEDURE sp; +# Another use case is when a temporary table hides a view is dropped +# inside a stored routine being called. +CREATE VIEW t1 AS SELECT 1; +CREATE PROCEDURE p1() +BEGIN +DROP TEMPORARY TABLE t1; +END +| +CREATE FUNCTION f1() RETURNS INT +BEGIN +CALL p1(); +RETURN 1; +END +| +CREATE TEMPORARY TABLE t1 AS SELECT 1 AS a; +PREPARE stmt FROM 'SELECT f1()'; +EXECUTE stmt; +f1() +1 +# The temporary table t1 has been dropped on first +# execution of the prepared statement 'stmt', +# next time this statement is run it results in issuing +# the error ER_BAD_TABLE_ERROR +EXECUTE stmt; +ERROR 42S02: Unknown table 'test.t1' +# Clean up +DROP VIEW t1; +DROP FUNCTION f1; +DROP PROCEDURE p1; +# # End of 10.4 tests # create function f1() returns int diff --git a/mysql-test/main/temp_table.test b/mysql-test/main/temp_table.test index 11a667435d1..529ce4a6af6 100644 --- a/mysql-test/main/temp_table.test +++ b/mysql-test/main/temp_table.test @@ -669,6 +669,60 @@ SHOW TABLES; DROP TEMPORARY TABLE t1, t2; +--echo # +--echo # MDEV-33218: Assertion `active_arena->is_stmt_prepare_or_first_stmt_execute() || active_arena->state == Query_arena::STMT_SP_QUERY_ARGUMENTS' failed. in st_select_lex::fix_prepare_information +--echo # +CREATE VIEW v1 AS SELECT 5; +CREATE PROCEDURE sp() SELECT * FROM v1; +CREATE TEMPORARY TABLE v1 as SELECT 7; +--echo # sp() accesses the temporary table v1 that hides the view with the same name +--echo # Therefore expected output is the row (7) +CALL sp(); +DROP TEMPORARY TABLE v1; +--echo # After the temporary table v1 has been dropped the next invocation of sp() +--echo # accesses the view v1. So, expected output is the row (5) +CALL sp(); + +--echo # Clean up +DROP VIEW v1; +DROP PROCEDURE sp; + +--echo # Another use case is when a temporary table hides a view is dropped +--echo # inside a stored routine being called. + +CREATE VIEW t1 AS SELECT 1; + +--delimiter | +CREATE PROCEDURE p1() +BEGIN + DROP TEMPORARY TABLE t1; +END +| + +CREATE FUNCTION f1() RETURNS INT +BEGIN + CALL p1(); + RETURN 1; +END +| + +--delimiter ; + +CREATE TEMPORARY TABLE t1 AS SELECT 1 AS a; +PREPARE stmt FROM 'SELECT f1()'; +EXECUTE stmt; +--echo # The temporary table t1 has been dropped on first +--echo # execution of the prepared statement 'stmt', +--echo # next time this statement is run it results in issuing +--echo # the error ER_BAD_TABLE_ERROR +--error ER_BAD_TABLE_ERROR +EXECUTE stmt; + +--echo # Clean up +DROP VIEW t1; +DROP FUNCTION f1; +DROP PROCEDURE p1; + --echo # --echo # End of 10.4 tests --echo # diff --git a/mysql-test/mariadb-test-run.pl b/mysql-test/mariadb-test-run.pl index 740a73aea7f..2e10cd74b79 100755 --- a/mysql-test/mariadb-test-run.pl +++ b/mysql-test/mariadb-test-run.pl @@ -4550,8 +4550,6 @@ sub extract_warning_lines ($$) { qr/WSREP: Guessing address for incoming client/, qr/InnoDB: Difficult to find free blocks in the buffer pool*/, - # for UBSAN - qr/decimal\.c.*: runtime error: signed integer overflow/, # Disable test for UBSAN on dynamically loaded objects qr/runtime error: member call.*object.*'Handler_share'/, qr/sql_type\.cc.* runtime error: member call.*object.* 'Type_collection'/, @@ -5711,6 +5709,8 @@ sub start_mysqltest ($) { mtr_add_arg($args, "--result-file=%s", $tinfo->{'result_file'}); } + mtr_add_arg($args, "--wait-for-pos-timeout=%d", $opt_debug_sync_timeout); + client_debug_arg($args, "mysqltest"); if ( $opt_record ) diff --git a/mysql-test/suite/binlog/include/binlog_index.inc b/mysql-test/suite/binlog/include/binlog_index.inc index da6cac18e30..69498f42b82 100644 --- a/mysql-test/suite/binlog/include/binlog_index.inc +++ b/mysql-test/suite/binlog/include/binlog_index.inc @@ -98,7 +98,7 @@ reset master; --echo # crash_purge_before_update_index flush logs; ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect SET SESSION debug_dbug="+d,crash_purge_before_update_index"; --source include/wait_for_binlog_checkpoint.inc --error 2013 @@ -119,7 +119,7 @@ SELECT @index; --echo # crash_purge_non_critical_after_update_index flush logs; ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect SET SESSION debug_dbug="+d,crash_purge_non_critical_after_update_index"; --source include/wait_for_binlog_checkpoint.inc --error 2013 @@ -143,7 +143,7 @@ SELECT @index; --echo # crash_purge_critical_after_update_index flush logs; ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect SET SESSION debug_dbug="+d,crash_purge_critical_after_update_index"; --source include/wait_for_binlog_checkpoint.inc --error 2013 @@ -167,7 +167,7 @@ file_exists $MYSQLD_DATADIR/master-bin.000008; SELECT @index; --echo # crash_create_non_critical_before_update_index ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect SET SESSION debug_dbug="+d,crash_create_non_critical_before_update_index"; --error 2013 flush logs; @@ -185,7 +185,7 @@ file_exists $MYSQLD_DATADIR/master-bin.000009; SELECT @index; --echo # crash_create_critical_before_update_index ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect SET SESSION debug_dbug="+d,crash_create_critical_before_update_index"; --error 2013 flush logs; @@ -205,7 +205,7 @@ file_exists $MYSQLD_DATADIR/master-bin.000011; SELECT @index; --echo # crash_create_after_update_index ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect SET SESSION debug_dbug="+d,crash_create_after_update_index"; --error 2013 flush logs; diff --git a/mysql-test/suite/binlog/t/binlog_autocommit_off_no_hang.test b/mysql-test/suite/binlog/t/binlog_autocommit_off_no_hang.test index 8f1dbb2a2dd..149b1a8d97d 100644 --- a/mysql-test/suite/binlog/t/binlog_autocommit_off_no_hang.test +++ b/mysql-test/suite/binlog/t/binlog_autocommit_off_no_hang.test @@ -26,10 +26,10 @@ ALTER TABLE mysql.gtid_slave_pos ENGINE=innodb; --echo # Restart the server so mysqld reads the gtid_slave_pos using innodb ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --shutdown_server --source include/wait_until_disconnected.inc ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --enable_reconnect --source include/wait_until_connected_again.inc diff --git a/mysql-test/suite/binlog/t/binlog_rotate_perf.test b/mysql-test/suite/binlog/t/binlog_rotate_perf.test index 74c91feca97..512471e2de1 100644 --- a/mysql-test/suite/binlog/t/binlog_rotate_perf.test +++ b/mysql-test/suite/binlog/t/binlog_rotate_perf.test @@ -68,10 +68,10 @@ while ($loop_times) { # try to change the log-bin configs and restart --echo # ======= now try to change the log-bin config for mysqld ======= ---let $restart_parameters="--log-bin=new_log_bin" +--let $restart_parameters=--log-bin=new_log_bin --echo #begin to restart mysqld --source include/restart_mysqld.inc ---let $restart_parameters= "" +--let $restart_parameters= --source include/show_binary_logs.inc let $loop_times= 10; diff --git a/mysql-test/suite/binlog_encryption/restart_server.inc b/mysql-test/suite/binlog_encryption/restart_server.inc index 8f0fe7d8970..f71858be741 100644 --- a/mysql-test/suite/binlog_encryption/restart_server.inc +++ b/mysql-test/suite/binlog_encryption/restart_server.inc @@ -20,7 +20,7 @@ --connection $_cur_con --enable_reconnect ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.$rpl_server_number.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.$rpl_server_number.expect shutdown_server; @@ -31,5 +31,5 @@ if ($rpl_server_parameters) { --let $_rpl_start_server_command= restart:$rpl_server_parameters } ---exec echo "$_rpl_start_server_command" > $MYSQLTEST_VARDIR/tmp/mysqld.$rpl_server_number.expect +--write_line "$_rpl_start_server_command" $MYSQLTEST_VARDIR/tmp/mysqld.$rpl_server_number.expect --source include/wait_until_connected_again.inc diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_slave_bgc_kill.result b/mysql-test/suite/binlog_encryption/rpl_parallel_slave_bgc_kill.result index ba131ea094f..6b75dbf6181 100644 --- a/mysql-test/suite/binlog_encryption/rpl_parallel_slave_bgc_kill.result +++ b/mysql-test/suite/binlog_encryption/rpl_parallel_slave_bgc_kill.result @@ -206,10 +206,12 @@ RETURN x; END || SET sql_log_bin=1; +include/stop_slave_io.inc connection server_1; INSERT INTO t3 VALUES (49,0); connection server_2; -START SLAVE SQL_THREAD; +CHANGE MASTER TO master_use_gtid=no; +include/start_slave.inc SELECT * FROM t3 WHERE a >= 40 ORDER BY a; a b 41 41 @@ -239,10 +241,6 @@ SET GLOBAL slave_parallel_threads=0; SET GLOBAL slave_parallel_threads=10; include/start_slave.inc *** 3. Same as (2), but not using gtid mode *** -connection server_2; -include/stop_slave.inc -CHANGE MASTER TO master_use_gtid=no; -include/start_slave.inc connection server_1; connection con_temp3; SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1'; diff --git a/mysql-test/suite/compat/oracle/r/gis.result b/mysql-test/suite/compat/oracle/r/gis.result index 113cb0ea402..8145b97d695 100644 --- a/mysql-test/suite/compat/oracle/r/gis.result +++ b/mysql-test/suite/compat/oracle/r/gis.result @@ -33,37 +33,37 @@ ERROR 42000: Incorrect parameter count in the call to native function 'WITHIN(PO # MDEV-20009 Add CAST(expr AS pluggable_type) # SELECT CAST(1 AS GEOMETRY); -ERROR HY000: Operator does not exists: 'CAST(expr AS geometry)' +ERROR HY000: Operator does not exist: 'CAST(expr AS geometry)' SELECT CAST(1 AS GEOMETRYCOLLECTION); -ERROR HY000: Operator does not exists: 'CAST(expr AS geometrycollection)' +ERROR HY000: Operator does not exist: 'CAST(expr AS geometrycollection)' SELECT CAST(1 AS POINT); -ERROR HY000: Operator does not exists: 'CAST(expr AS point)' +ERROR HY000: Operator does not exist: 'CAST(expr AS point)' SELECT CAST(1 AS LINESTRING); -ERROR HY000: Operator does not exists: 'CAST(expr AS linestring)' +ERROR HY000: Operator does not exist: 'CAST(expr AS linestring)' SELECT CAST(1 AS POLYGON); -ERROR HY000: Operator does not exists: 'CAST(expr AS polygon)' +ERROR HY000: Operator does not exist: 'CAST(expr AS polygon)' SELECT CAST(1 AS MULTIPOINT); -ERROR HY000: Operator does not exists: 'CAST(expr AS multipoint)' +ERROR HY000: Operator does not exist: 'CAST(expr AS multipoint)' SELECT CAST(1 AS MULTILINESTRING); -ERROR HY000: Operator does not exists: 'CAST(expr AS multilinestring)' +ERROR HY000: Operator does not exist: 'CAST(expr AS multilinestring)' SELECT CAST(1 AS MULTIPOLYGON); -ERROR HY000: Operator does not exists: 'CAST(expr AS multipolygon)' +ERROR HY000: Operator does not exist: 'CAST(expr AS multipolygon)' SELECT CONVERT(1, GEOMETRY); -ERROR HY000: Operator does not exists: 'CAST(expr AS geometry)' +ERROR HY000: Operator does not exist: 'CAST(expr AS geometry)' SELECT CONVERT(1, GEOMETRYCOLLECTION); -ERROR HY000: Operator does not exists: 'CAST(expr AS geometrycollection)' +ERROR HY000: Operator does not exist: 'CAST(expr AS geometrycollection)' SELECT CONVERT(1, POINT); -ERROR HY000: Operator does not exists: 'CAST(expr AS point)' +ERROR HY000: Operator does not exist: 'CAST(expr AS point)' SELECT CONVERT(1, LINESTRING); -ERROR HY000: Operator does not exists: 'CAST(expr AS linestring)' +ERROR HY000: Operator does not exist: 'CAST(expr AS linestring)' SELECT CONVERT(1, POLYGON); -ERROR HY000: Operator does not exists: 'CAST(expr AS polygon)' +ERROR HY000: Operator does not exist: 'CAST(expr AS polygon)' SELECT CONVERT(1, MULTIPOINT); -ERROR HY000: Operator does not exists: 'CAST(expr AS multipoint)' +ERROR HY000: Operator does not exist: 'CAST(expr AS multipoint)' SELECT CONVERT(1, MULTILINESTRING); -ERROR HY000: Operator does not exists: 'CAST(expr AS multilinestring)' +ERROR HY000: Operator does not exist: 'CAST(expr AS multilinestring)' SELECT CONVERT(1, MULTIPOLYGON); -ERROR HY000: Operator does not exists: 'CAST(expr AS multipolygon)' +ERROR HY000: Operator does not exist: 'CAST(expr AS multipolygon)' # # End of 10.5 tests # diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change3.test b/mysql-test/suite/encryption/t/innodb-bad-key-change3.test index 9c2918f3118..f4065290938 100644 --- a/mysql-test/suite/encryption/t/innodb-bad-key-change3.test +++ b/mysql-test/suite/encryption/t/innodb-bad-key-change3.test @@ -16,7 +16,7 @@ call mtr.add_suppression("InnoDB: Cannot calculate statistics for table .* becau --let $MYSQLD_DATADIR = `SELECT @@datadir` --let SEARCH_RANGE = 10000000 --let t1_IBD = $MYSQLD_DATADIR/test/t1.ibd ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --shutdown_server --source include/wait_until_disconnected.inc @@ -25,7 +25,7 @@ call mtr.add_suppression("InnoDB: Cannot calculate statistics for table .* becau 4;770A8A65DA156D24EE2A093277530143 EOF ---exec echo "restart:--innodb-encrypt-tables --innodb-stats-persistent --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys1.txt" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line "restart:--innodb-encrypt-tables --innodb-stats-persistent --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys1.txt" $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --enable_reconnect --source include/wait_until_connected_again.inc @@ -47,7 +47,7 @@ UNLOCK TABLES; ALTER TABLE t1 DISCARD TABLESPACE; ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --shutdown_server --source include/wait_until_disconnected.inc @@ -62,7 +62,7 @@ ib_discard_tablespaces("test", "t1"); ib_restore_tablespaces("test", "t1"); EOF ---exec echo "restart:--innodb-encrypt-tables --innodb-stats-persistent --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys2.txt" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line "restart:--innodb-encrypt-tables --innodb-stats-persistent --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys2.txt" $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --enable_reconnect --source include/wait_until_connected_again.inc --source include/restart_mysqld.inc @@ -80,7 +80,7 @@ SELECT * FROM t1; -- let SEARCH_FILE=$t1_IBD -- source include/search_pattern_in_file.inc ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --shutdown_server --source include/wait_until_disconnected.inc --remove_file $MYSQLTEST_VARDIR/keys1.txt @@ -89,7 +89,7 @@ SELECT * FROM t1; 4;770A8A65DA156D24EE2A093277530143 EOF ---exec echo "restart:--innodb-encrypt-tables --innodb-stats-persistent --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys1.txt" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line "restart:--innodb-encrypt-tables --innodb-stats-persistent --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys1.txt" $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --enable_reconnect --source include/wait_until_connected_again.inc DROP TABLE t1; diff --git a/mysql-test/suite/encryption/t/innodb_encrypt_freed.test b/mysql-test/suite/encryption/t/innodb_encrypt_freed.test index 7ba0b5a2d1a..26c1e8dfee5 100644 --- a/mysql-test/suite/encryption/t/innodb_encrypt_freed.test +++ b/mysql-test/suite/encryption/t/innodb_encrypt_freed.test @@ -21,7 +21,7 @@ CREATE TABLE t1(f1 BIGINT PRIMARY KEY, f2 int not null, SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0; CREATE TABLE t2 (f1 int not null)engine=innodb; -let $restart_parameters="--debug=d,ib_log_checkpoint_avoid"; +let $restart_parameters=--debug=d,ib_log_checkpoint_avoid; --source include/restart_mysqld.inc # Stop the purge diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 2d8e5e6299d..cca798a9eed 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -22,7 +22,7 @@ galera_concurrent_ctas : MDEV-32779 galera_concurrent_ctas: assertion in the gal galera_as_slave_replay : MDEV-32780 galera_as_slave_replay: assertion in the wsrep::transaction::before_rollback() galera_slave_replay : MDEV-32780 galera_as_slave_replay: assertion in the wsrep::transaction::before_rollback() galera_sst_mysqldump_with_key : MDEV-32782 galera_sst_mysqldump_with_key test failed -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 galera_desync_overlapped : MDEV-21538 galera_desync_overlapped MTR failed: Result content mismatch +galera_create_table_as_select : MDEV-33952 fails sporadically diff --git a/mysql-test/suite/galera/include/kill_galera.inc b/mysql-test/suite/galera/include/kill_galera.inc index 28a1b0f368c..3c218a19bee 100644 --- a/mysql-test/suite/galera/include/kill_galera.inc +++ b/mysql-test/suite/galera/include/kill_galera.inc @@ -8,7 +8,7 @@ if (!$kill_signal) # Write file to make mysql-test-run.pl expect the crash, but don't start it --let $_expect_file_name= `select regexp_replace(@@tmpdir, '^.*/','')` --let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/$_expect_file_name.expect ---exec echo "wait" > $_expect_file_name +--write_line wait $_expect_file_name # Kill the connected server --disable_reconnect diff --git a/mysql-test/suite/galera/include/shutdown_mysqld.inc b/mysql-test/suite/galera/include/shutdown_mysqld.inc deleted file mode 100644 index 793be8d76ac..00000000000 --- a/mysql-test/suite/galera/include/shutdown_mysqld.inc +++ /dev/null @@ -1,18 +0,0 @@ -# This is the first half of include/restart_mysqld.inc. -if ($rpl_inited) -{ - if (!$allow_rpl_inited) - { - --die ERROR IN TEST: When using the replication test framework (master-slave.inc, rpl_init.inc etc), use rpl_restart_server.inc instead of restart_mysqld.inc. If you know what you are doing and you really have to use restart_mysqld.inc, set allow_rpl_inited=1 before you source restart_mysqld.inc - } -} - -# Write file to make mysql-test-run.pl expect the "crash", but don't start it ---let $_expect_file_name= `select regexp_replace(@@tmpdir, '^.*/','')` ---let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/$_expect_file_name.expect ---exec echo "wait" > $_expect_file_name - -# Send shutdown to the connected server ---shutdown_server ---source include/wait_until_disconnected.inc - diff --git a/mysql-test/suite/galera/include/start_mysqld.inc b/mysql-test/suite/galera/include/start_mysqld.inc index 57af9203d0f..c9bed71f517 100644 --- a/mysql-test/suite/galera/include/start_mysqld.inc +++ b/mysql-test/suite/galera/include/start_mysqld.inc @@ -4,12 +4,12 @@ if ($galera_wsrep_start_position != '') { --echo Using --wsrep-start-position when starting mysqld ... - --exec echo "restart:$start_mysqld_params --wsrep-start-position=$galera_wsrep_start_position" > $_expect_file_name + --write_line "restart:$start_mysqld_params --wsrep-start-position=$galera_wsrep_start_position" $_expect_file_name --let $galera_wsrep_start_position = 0 } if ($galera_wsrep_start_position == '') { - --exec echo "restart:$start_mysqld_params" > $_expect_file_name + --write_line "restart:$start_mysqld_params" $_expect_file_name } --source include/galera_wait_ready.inc diff --git a/mysql-test/suite/galera/r/MDEV-25731.result b/mysql-test/suite/galera/r/MDEV-25731.result index c750affda3e..11a72730fb1 100644 --- a/mysql-test/suite/galera/r/MDEV-25731.result +++ b/mysql-test/suite/galera/r/MDEV-25731.result @@ -17,8 +17,11 @@ SELECT COUNT(*) AS EXPECT_6 FROM t1; EXPECT_6 6 connection node_1; -ALTER TABLE t1 ENGINE=InnoDB; +ALTER TABLE t1 ENGINE=Aria; +SET GLOBAL wsrep_mode=REPLICATE_ARIA; 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_12 FROM t1; EXPECT_12 12 @@ -27,6 +30,16 @@ SELECT COUNT(*) AS EXPECT_12 FROM t1; EXPECT_12 12 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_18 FROM t1; +EXPECT_18 +18 +connection node_2; +SELECT COUNT(*) AS EXPECT_18 FROM t1; +EXPECT_18 +18 +connection node_1; DROP TABLE t1; SET GLOBAL wsrep_load_data_splitting=OFF; Warnings: diff --git a/mysql-test/suite/galera/r/MDEV-26499.result b/mysql-test/suite/galera/r/MDEV-26499.result new file mode 100644 index 00000000000..15d372470a4 --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-26499.result @@ -0,0 +1,6 @@ +connection node_2; +connection node_1; +connection node_1; +connection node_2; +connection node_2; +SET GLOBAL debug_dbug="+d,simulate_slow_client_at_shutdown"; diff --git a/mysql-test/suite/galera/r/MDEV-27806.result b/mysql-test/suite/galera/r/MDEV-27806.result index 0f7ac79e4cd..6fe288f4e8e 100644 --- a/mysql-test/suite/galera/r/MDEV-27806.result +++ b/mysql-test/suite/galera/r/MDEV-27806.result @@ -37,7 +37,7 @@ mysqld-bin.000002 # Gtid # # BEGIN GTID #-#-# mysqld-bin.000002 # Query # # use `test`; CREATE TABLE `ts1` ( `f1` int(11) NOT NULL ) -mysqld-bin.000002 # Xid # # COMMIT /* XID */ +mysqld-bin.000002 # Query # # COMMIT connection node_2; include/show_binlog_events.inc Log_name Pos Event_type Server_id End_log_pos Info diff --git a/mysql-test/suite/galera/r/MDEV-33828.result b/mysql-test/suite/galera/r/MDEV-33828.result new file mode 100644 index 00000000000..a3ce68166ab --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-33828.result @@ -0,0 +1,41 @@ +connection node_2; +connection node_1; +SET AUTOCOMMIT=ON; +SELECT @@autocommit; +@@autocommit +1 +SET LOCAL enforce_storage_engine=InnoDB; +CREATE TABLE t1(id int not null primary key auto_increment, name varchar(64)) ENGINE=InnoDB; +INSERT INTO t1(name) VALUES ('name1'),('name3'),('name6'),('name2'); +CREATE PROCEDURE sel_proc() +BEGIN +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END; +SELECT * FROM t1; +END| +CREATE PROCEDURE ins_proc() +BEGIN +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END; +INSERT INTO t1 VALUES ('name_proc'); +END| +SET AUTOCOMMIT=OFF; +SELECT @@autocommit; +@@autocommit +0 +START TRANSACTION; +insert into t1(name) values('name10'); +select param_list, returns, db, type from mysql.proc where name='sel_proc'; +param_list returns db type + test PROCEDURE +call ins_proc(); +COMMIT; +SET AUTOCOMMIT=ON; +SELECT * FROM t1; +id name +1 name1 +3 name3 +5 name6 +7 name2 +9 name10 +DROP TABLE t1; +DROP PROCEDURE sel_proc; +DROP PROCEDURE ins_proc; diff --git a/mysql-test/suite/galera/r/galera_table_with_hyphen.result b/mysql-test/suite/galera/r/galera_table_with_hyphen.result new file mode 100644 index 00000000000..c9993004b53 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_table_with_hyphen.result @@ -0,0 +1,52 @@ +connection node_2; +connection node_1; +connection node_1; +set wsrep_sync_wait=0; +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET SESSION wsrep_sync_wait = 0; +connection node_1; +SET GLOBAL wsrep_slave_threads=2; +CREATE TABLE `par-ent` ( id INT AUTO_INCREMENT PRIMARY KEY, j INT) ENGINE=InnoDB; +CREATE TABLE `child` (id INT AUTO_INCREMENT PRIMARY KEY, parent_id INT, j INT, FOREIGN KEY (parent_id) REFERENCES `par-ent`(id)) ENGINE=InnoDB; +INSERT INTO `par-ent` VALUES (23,0); +connection node_2; +connection node_1a; +SET GLOBAL DEBUG_DBUG='+d,wsrep_ha_write_row'; +connection node_2; +INSERT INTO `child` VALUES (21,23,0),(22,23,0),(23,23,0); +connection node_1a; +SET DEBUG_SYNC='now WAIT_FOR wsrep_ha_write_row_reached'; +connection node_2; +UPDATE `par-ent` SET j=2 WHERE id=23; +connection node_1a; +SET GLOBAL DEBUG_DBUG='-d,wsrep_ha_write_row'; +SET DEBUG_SYNC='now SIGNAL wsrep_ha_write_row_continue'; +SET GLOBAL DEBUG_DBUG="RESET"; +SET DEBUG_SYNC = 'RESET'; +SET GLOBAL wsrep_slave_threads=DEFAULT; +connection node_2; +drop table `child`; +drop table `par-ent`; +connection node_1; +SET GLOBAL wsrep_slave_threads=2; +CREATE TABLE `p-arent-` ( id INT AUTO_INCREMENT PRIMARY KEY, j INT) ENGINE=InnoDB; +CREATE TABLE `c-hild` (id INT AUTO_INCREMENT PRIMARY KEY, parent_id INT, j INT, FOREIGN KEY (parent_id) REFERENCES `p-arent-`(id)) ENGINE=InnoDB; +INSERT INTO `p-arent-` VALUES (23,0); +connection node_2; +connection node_1a; +SET GLOBAL DEBUG_DBUG='+d,wsrep_ha_write_row'; +connection node_2; +INSERT INTO `c-hild` VALUES (21,23,0),(22,23,0),(23,23,0); +connection node_1a; +SET DEBUG_SYNC='now WAIT_FOR wsrep_ha_write_row_reached'; +connection node_2; +UPDATE `p-arent-` SET j=2 WHERE id=23; +connection node_1a; +SET GLOBAL DEBUG_DBUG='-d,wsrep_ha_write_row'; +SET DEBUG_SYNC='now SIGNAL wsrep_ha_write_row_continue'; +SET GLOBAL DEBUG_DBUG="RESET"; +SET DEBUG_SYNC = 'RESET'; +SET GLOBAL wsrep_slave_threads=DEFAULT; +connection node_2; +drop table `c-hild`; +drop table `p-arent-`; diff --git a/mysql-test/suite/galera/r/mdev-22063.result b/mysql-test/suite/galera/r/mdev-22063.result index c594bc47b95..155d1ebbe4f 100644 --- a/mysql-test/suite/galera/r/mdev-22063.result +++ b/mysql-test/suite/galera/r/mdev-22063.result @@ -78,7 +78,6 @@ 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; @@ -96,9 +95,9 @@ EXPECT_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 t6; +EXPECT_1000 +1000 SELECT COUNT(*) AS EXPECT_1000 FROM t7; EXPECT_1000 1000 @@ -121,9 +120,9 @@ EXPECT_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 t6; +EXPECT_1000 +1000 SELECT COUNT(*) AS EXPECT_1000 FROM t7; EXPECT_1000 1000 @@ -147,7 +146,6 @@ 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; @@ -165,9 +163,9 @@ EXPECT_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 t6; +EXPECT_1000 +1000 SELECT COUNT(*) AS EXPECT_1000 FROM t7; EXPECT_1000 1000 @@ -190,9 +188,9 @@ EXPECT_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 t6; +EXPECT_1000 +1000 SELECT COUNT(*) AS EXPECT_1000 FROM t7; EXPECT_1000 1000 diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index f6caecdc36a..4c4d26db4c5 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -1,5 +1,6 @@ package My::Suite::Galera; +use warnings; use lib 'suite'; use wsrep::common; @@ -63,6 +64,7 @@ push @::global_suppressions, qr(WSREP: Failed to remove page file .*), qr(WSREP: wsrep_sst_method is set to 'mysqldump' yet mysqld bind_address is set to .*), qr|WSREP: Sending JOIN failed: -107 \(Transport endpoint is not connected\). Will retry in new primary component.|, + qr|WSREP: Send action \{.* STATE_REQUEST} returned -107 \(Transport endpoint is not connected\)|, qr|WSREP: Trying to continue unpaused monitor|, qr|WSREP: Wait for gtid returned error 3 while waiting for prior transactions to commit before setting position|, qr|WSREP: Failed to report last committed|, diff --git a/mysql-test/suite/galera/t/MDEV-25731.test b/mysql-test/suite/galera/t/MDEV-25731.test index 8f5439704e8..893cccbb2bd 100644 --- a/mysql-test/suite/galera/t/MDEV-25731.test +++ b/mysql-test/suite/galera/t/MDEV-25731.test @@ -12,16 +12,23 @@ SELECT COUNT(*) AS EXPECT_6 FROM t1; SELECT COUNT(*) AS EXPECT_6 FROM t1; --connection node_1 -ALTER TABLE t1 ENGINE=InnoDB; +ALTER TABLE t1 ENGINE=Aria; +SET GLOBAL wsrep_mode=REPLICATE_ARIA; 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 +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_18 FROM t1; + +--connection node_2 +SELECT COUNT(*) AS EXPECT_18 FROM t1; + --connection node_1 DROP TABLE t1; SET GLOBAL wsrep_load_data_splitting=OFF; SET GLOBAL wsrep_mode=DEFAULT; - - diff --git a/mysql-test/suite/galera/t/MDEV-26499.test b/mysql-test/suite/galera/t/MDEV-26499.test new file mode 100644 index 00000000000..824b28c14f3 --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-26499.test @@ -0,0 +1,20 @@ +# +# MDEV-26499 +# +# This test reproduces some failure on mysql_shutdown() call +# which manifests sporadically in some galera MTR tests during +# restart of a node. +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc + +--let $node_1=node_1 +--let $node_2=node_2 +--source include/auto_increment_offset_save.inc + +--connection node_2 +SET GLOBAL debug_dbug="+d,simulate_slow_client_at_shutdown"; +--source include/restart_mysqld.inc + +--source include/auto_increment_offset_restore.inc diff --git a/mysql-test/suite/galera/t/MDEV-33828.cnf b/mysql-test/suite/galera/t/MDEV-33828.cnf new file mode 100644 index 00000000000..4c62448fe3d --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-33828.cnf @@ -0,0 +1,4 @@ +!include ../galera_2nodes.cnf + +[mysqld] +log-bin diff --git a/mysql-test/suite/galera/t/MDEV-33828.test b/mysql-test/suite/galera/t/MDEV-33828.test new file mode 100644 index 00000000000..8e30481beee --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-33828.test @@ -0,0 +1,45 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_aria.inc + +SET AUTOCOMMIT=ON; +SELECT @@autocommit; + +SET LOCAL enforce_storage_engine=InnoDB; + +CREATE TABLE t1(id int not null primary key auto_increment, name varchar(64)) ENGINE=InnoDB; +INSERT INTO t1(name) VALUES ('name1'),('name3'),('name6'),('name2'); + +DELIMITER |; +CREATE PROCEDURE sel_proc() +BEGIN + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END; + SELECT * FROM t1; +END| + +CREATE PROCEDURE ins_proc() +BEGIN + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END; + INSERT INTO t1 VALUES ('name_proc'); +END| +DELIMITER ;| + +SET AUTOCOMMIT=OFF; +SELECT @@autocommit; + +START TRANSACTION; + +insert into t1(name) values('name10'); + +select param_list, returns, db, type from mysql.proc where name='sel_proc'; + +call ins_proc(); + +COMMIT; + +SET AUTOCOMMIT=ON; + +SELECT * FROM t1; +DROP TABLE t1; +DROP PROCEDURE sel_proc; +DROP PROCEDURE ins_proc; diff --git a/mysql-test/suite/galera/t/galera_ist_restart_joiner.test b/mysql-test/suite/galera/t/galera_ist_restart_joiner.test index b36a0de57b6..940b511f752 100644 --- a/mysql-test/suite/galera/t/galera_ist_restart_joiner.test +++ b/mysql-test/suite/galera/t/galera_ist_restart_joiner.test @@ -37,7 +37,7 @@ UPDATE t1 SET f2 = 'c' WHERE f1 > 2; # Write file to make mysql-test-run.pl expect the crash, but don't start it --let $_expect_file_name= `select regexp_replace(@@tmpdir, '^.*/','')` --let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/$_expect_file_name.expect ---exec echo "wait" > $_expect_file_name +--write_line wait $_expect_file_name --let KILL_NODE_PIDFILE = `SELECT @@pid_file` diff --git a/mysql-test/suite/galera/t/galera_pc_recovery.test b/mysql-test/suite/galera/t/galera_pc_recovery.test index 1621414aff5..16abe6fc9ba 100644 --- a/mysql-test/suite/galera/t/galera_pc_recovery.test +++ b/mysql-test/suite/galera/t/galera_pc_recovery.test @@ -27,8 +27,8 @@ INSERT INTO t1 VALUES (1); SELECT COUNT(*) = 1 FROM t1; --let $NODE_2_PIDFILE = `SELECT @@pid_file` ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.2.expect --exec kill -9 `cat $NODE_1_PIDFILE` `cat $NODE_2_PIDFILE` # Perform --wsrep-recover and preserve the positions into variables by placing them in $MYSQL_TMP_DIR/galera_wsrep_start_position.inc and then --source'ing it @@ -66,8 +66,8 @@ if ($galera_wsrep_start_position2 == '') { # Instruct MTR to perform the actual restart using --wsrep-start-position . Proper --wsrep_cluster_address is used as my.cnf only contains 'gcomm://' for node #1 ---exec echo "restart: --wsrep-start-position=$galera_wsrep_start_position1 --wsrep_cluster_address=gcomm://127.0.0.1:$NODE_GALERAPORT_1,127.0.0.1:$NODE_GALERAPORT_2" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect ---exec echo "restart: --wsrep-start-position=$galera_wsrep_start_position2 --wsrep_cluster_address=gcomm://127.0.0.1:$NODE_GALERAPORT_1,127.0.0.1:$NODE_GALERAPORT_2" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +--write_line "restart: --wsrep-start-position=$galera_wsrep_start_position1 --wsrep_cluster_address=gcomm://127.0.0.1:$NODE_GALERAPORT_1,127.0.0.1:$NODE_GALERAPORT_2" $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line "restart: --wsrep-start-position=$galera_wsrep_start_position2 --wsrep_cluster_address=gcomm://127.0.0.1:$NODE_GALERAPORT_1,127.0.0.1:$NODE_GALERAPORT_2" $MYSQLTEST_VARDIR/tmp/mysqld.2.expect --sleep 5 --connection node_1 diff --git a/mysql-test/suite/galera/t/galera_restart_on_unknown_option.test b/mysql-test/suite/galera/t/galera_restart_on_unknown_option.test index 6a0f24dbaae..e3a8b749cb4 100644 --- a/mysql-test/suite/galera/t/galera_restart_on_unknown_option.test +++ b/mysql-test/suite/galera/t/galera_restart_on_unknown_option.test @@ -62,7 +62,7 @@ SELECT * FROM t1; --let $start_mysqld_params=--galera-unknown-option --echo Starting server ... ---exec echo "try:$start_mysqld_params" > $_expect_file_name +--write_line "try:$start_mysqld_params" $_expect_file_name # Sleep to ensure that server exited... @@ -107,7 +107,7 @@ SELECT * FROM t1; --let $start_mysqld_params=--galera-unknown-option --echo Starting server ... ---exec echo "try:$start_mysqld_params" > $_expect_file_name +--write_line "try:$start_mysqld_params" $_expect_file_name # Sleep to ensure that server exited... diff --git a/mysql-test/suite/galera/t/galera_table_with_hyphen.inc b/mysql-test/suite/galera/t/galera_table_with_hyphen.inc new file mode 100644 index 00000000000..ac79d864e82 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_table_with_hyphen.inc @@ -0,0 +1,48 @@ +# +# parameters: +# $fk_child - child table name +# $fk_parent - parent table name +# +--connection node_1 +SET GLOBAL wsrep_slave_threads=2; + +--eval CREATE TABLE `$fk_parent` ( id INT AUTO_INCREMENT PRIMARY KEY, j INT) ENGINE=InnoDB + +--eval CREATE TABLE `$fk_child` (id INT AUTO_INCREMENT PRIMARY KEY, parent_id INT, j INT, FOREIGN KEY (parent_id) REFERENCES `$fk_parent`(id)) ENGINE=InnoDB + +--eval INSERT INTO `$fk_parent` VALUES (23,0) + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM `$fk_parent`; +--source include/wait_condition.inc + +--connection node_1a +SET GLOBAL DEBUG_DBUG='+d,wsrep_ha_write_row'; + +--connection node_2 +--eval INSERT INTO `$fk_child` VALUES (21,23,0),(22,23,0),(23,23,0) + +--connection node_1a +SET DEBUG_SYNC='now WAIT_FOR wsrep_ha_write_row_reached'; + +--let $wsrep_received_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_received'` + +--connection node_2 +--eval UPDATE `$fk_parent` SET j=2 WHERE id=23 + +--connection node_1a +--let $wait_condition = SELECT VARIABLE_VALUE = $wsrep_received_before + 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_received' +--source include/wait_condition.inc + +SET GLOBAL DEBUG_DBUG='-d,wsrep_ha_write_row'; +SET DEBUG_SYNC='now SIGNAL wsrep_ha_write_row_continue'; + +SET GLOBAL DEBUG_DBUG="RESET"; +SET DEBUG_SYNC = 'RESET'; + +SET GLOBAL wsrep_slave_threads=DEFAULT; + +--connection node_2 +--eval drop table `$fk_child` +--eval drop table `$fk_parent` + diff --git a/mysql-test/suite/galera/t/galera_table_with_hyphen.test b/mysql-test/suite/galera/t/galera_table_with_hyphen.test new file mode 100644 index 00000000000..1b28bdeb3ca --- /dev/null +++ b/mysql-test/suite/galera/t/galera_table_with_hyphen.test @@ -0,0 +1,34 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +# +# Testing how tables and databases with special characters +# are treated in certification +# +# The test creates two tables having foreign key constraint +# reference and executes two transactions which modify +# same rows. The same test is executed with different names +# containin special characters to see if the certification +# can detect the conflicts +# +# Actual test is in include file galera_table_with_hyphen.inc +# It create the test tables from parameters $fk_child and +# $fk_parent +# +--connection node_1 +set wsrep_sync_wait=0; + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET SESSION wsrep_sync_wait = 0; + +--let $fk_child = child +--let $fk_parent = par-ent + +--source galera_table_with_hyphen.inc + +--let $fk_child = c-hild +--let $fk_parent = p-arent- + +--source galera_table_with_hyphen.inc diff --git a/mysql-test/suite/galera/t/mdev-22063.test b/mysql-test/suite/galera/t/mdev-22063.test index 6a8f1ffa6ce..d0f3e3bc4b4 100644 --- a/mysql-test/suite/galera/t/mdev-22063.test +++ b/mysql-test/suite/galera/t/mdev-22063.test @@ -79,8 +79,6 @@ 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; @@ -90,7 +88,7 @@ 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 t6; SELECT COUNT(*) AS EXPECT_1000 FROM t7; SELECT COUNT(*) AS EXPECT_1000 FROM t8; @@ -105,7 +103,7 @@ 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 t6; SELECT COUNT(*) AS EXPECT_1000 FROM t7; SELECT COUNT(*) AS EXPECT_1000 FROM t8; @@ -129,8 +127,6 @@ 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; @@ -140,7 +136,7 @@ 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 t6; SELECT COUNT(*) AS EXPECT_1000 FROM t7; SELECT COUNT(*) AS EXPECT_1000 FROM t8; @@ -155,7 +151,7 @@ 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 t6; SELECT COUNT(*) AS EXPECT_1000 FROM t7; SELECT COUNT(*) AS EXPECT_1000 FROM t8; diff --git a/mysql-test/suite/galera/t/mdev-22543.test b/mysql-test/suite/galera/t/mdev-22543.test index 1e7d3712639..26257b28814 100644 --- a/mysql-test/suite/galera/t/mdev-22543.test +++ b/mysql-test/suite/galera/t/mdev-22543.test @@ -36,7 +36,7 @@ SET DEBUG_SYNC = "now WAIT_FOR sync_point_reached"; # Restart without waiting. The UPDATE should block FTWRL on node_1, # so the SST cannot be completed and node_2 cannot join before # UPDATE connection is signalled to continue. ---exec echo "restart:$start_mysqld_params" > $_expect_file_name +--write_line "restart:$start_mysqld_params" $_expect_file_name # If the bug is present, FTWRL times out on node_1 in couple of # seconds and node_2 fails to join. --sleep 10 diff --git a/mysql-test/suite/galera/t/mdev-30013.test b/mysql-test/suite/galera/t/mdev-30013.test index 038b66600ce..3795dd32306 100644 --- a/mysql-test/suite/galera/t/mdev-30013.test +++ b/mysql-test/suite/galera/t/mdev-30013.test @@ -1,4 +1,5 @@ --source include/galera_cluster.inc +--source include/force_restart.inc # ARCHIVE plugin must be uninstalled if (!$HA_ARCHIVE_SO) { skip Needs Archive loadable plugin; diff --git a/mysql-test/suite/galera_3nodes/disabled.def b/mysql-test/suite/galera_3nodes/disabled.def index 728500f45fc..ffed5432097 100644 --- a/mysql-test/suite/galera_3nodes/disabled.def +++ b/mysql-test/suite/galera_3nodes/disabled.def @@ -19,3 +19,5 @@ galera_ipv6_mariabackup_section : temporarily disabled at the request of Codersh # Opensuse/suse/rocky9/rocky84/rhel9/rhel8-ppc64le .. - all same IPv6 isn't configured right or skipping or galera galera_ipv6_rsync : Can't connect to server on '::1' (115) galera_ipv6_rsync_section : Can't connect to server on '::1' (115) +MDEV-29171 : MDEV-33842 galera_3nodes.MDEV-29171 fails on shutdown_server +GCF-354 : MDEV-25614 Galera test failure on GCF-354 diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-832.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-832.test index 2ecf5931b2a..700b3c38b6b 100644 --- a/mysql-test/suite/galera_3nodes_sr/t/GCF-832.test +++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-832.test @@ -21,7 +21,7 @@ SET GLOBAL debug_dbug="d,crash_last_fragment_commit_after_fragment_removal"; --let $_expect_file_name= `select regexp_replace(@@tmpdir, '^.*/','')` --let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/$_expect_file_name.expect ---exec echo "wait" > $_expect_file_name +--write_line wait $_expect_file_name CREATE TABLE t1 (f1 VARCHAR(30) not null primary key) ENGINE=InnoDB; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_bf_abort_idle.result b/mysql-test/suite/galera_sr/r/galera_sr_bf_abort_idle.result new file mode 100644 index 00000000000..a1495f1c138 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_bf_abort_idle.result @@ -0,0 +1,33 @@ +connection node_2; +connection node_1; +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER); +INSERT INTO t1 VALUES (1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1); +SET SESSION wsrep_trx_fragment_size=10; +SET SESSION wsrep_trx_fragment_unit='rows'; +START TRANSACTION; +UPDATE t1 SET f2 = f2 + 10; +connection node_2; +INSERT INTO t1 VALUES (10,2); +connection node_1a; +connection node_1; +INSERT INTO t1 VALUES (9,1); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +ROLLBACK; +DROP TABLE t1; +connection node_1; +CREATE TABLE t1(f1 INTEGER PRIMARY KEY, f2 INTEGER); +INSERT INTO t1 VALUES (1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1); +SET SESSION wsrep_trx_fragment_size=5; +SET SESSION wsrep_trx_fragment_unit='rows'; +START TRANSACTION; +UPDATE t1 SET f2 = f2 + 10; +connection node_2; +INSERT INTO t1 VALUES (10,2); +connection node_1a; +connection node_1; +INSERT INTO t1 VALUES (9,1); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +ROLLBACK; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/MDEV-25718.test b/mysql-test/suite/galera_sr/t/MDEV-25718.test index 9aebbdc7c5c..037cd300709 100644 --- a/mysql-test/suite/galera_sr/t/MDEV-25718.test +++ b/mysql-test/suite/galera_sr/t/MDEV-25718.test @@ -43,8 +43,9 @@ SET SESSION wsrep_sync_wait = 0; SET debug_sync = "now SIGNAL write_row_continue"; # Let's give the INSERT some time, to make sure it does rollback ---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = "INSERT INTO t1 VALUES (1)" AND STATE = "Freeing items"; ---source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = "INSERT INTO t1 VALUES (1)" AND (STATE = "Freeing items" OR STATE = 'Rollback'); +--let $wait_condition_on_error_output = SELECT INFO, STATE FROM INFORMATION_SCHEMA.PROCESSLIST +--source include/wait_condition_with_debug.inc # Resume the DDL in streaming_rollback SET SESSION debug_sync = "now SIGNAL wsrep_streaming_rollback_continue"; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_bf_abort_idle.test b/mysql-test/suite/galera_sr/t/galera_sr_bf_abort_idle.test new file mode 100644 index 00000000000..66259b790cc --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_bf_abort_idle.test @@ -0,0 +1,68 @@ +# +# Test BF abort for idle SR transactions +# + +--source include/galera_cluster.inc + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 + +# +# Case 1: BF abort idle SR transaction that has not yet replicated any fragments +# +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER); +INSERT INTO t1 VALUES (1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1); + +--let $bf_count = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.global_status WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts'` + +SET SESSION wsrep_trx_fragment_size=10; +SET SESSION wsrep_trx_fragment_unit='rows'; +START TRANSACTION; +UPDATE t1 SET f2 = f2 + 10; + +--connection node_2 +INSERT INTO t1 VALUES (10,2); + +# Wait for SR transaction to be BF aborted +--connection node_1a +--let $wait_condition = SELECT VARIABLE_VALUE = $bf_count + 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts' +--source include/wait_condition.inc + + +--connection node_1 +--error ER_LOCK_DEADLOCK +INSERT INTO t1 VALUES (9,1); +ROLLBACK; + +DROP TABLE t1; + + +# +# Case 2: BF abort idle SR transaction that has already replicated a fragment +# +--connection node_1 +CREATE TABLE t1(f1 INTEGER PRIMARY KEY, f2 INTEGER); +INSERT INTO t1 VALUES (1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1); + +--let $bf_count = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.global_status WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts'` + + +SET SESSION wsrep_trx_fragment_size=5; +SET SESSION wsrep_trx_fragment_unit='rows'; +START TRANSACTION; +UPDATE t1 SET f2 = f2 + 10; + +--connection node_2 +INSERT INTO t1 VALUES (10,2); + +# Wait for SR transaction to be BF aborted +--connection node_1a +--let $wait_condition = SELECT VARIABLE_VALUE = $bf_count + 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts' +--source include/wait_condition.inc + +--connection node_1 +--error ER_LOCK_DEADLOCK +INSERT INTO t1 VALUES (9,1); +ROLLBACK; + +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/check_ibd_filesize,32k.rdiff b/mysql-test/suite/innodb/r/check_ibd_filesize,32k.rdiff index 44446602b9f..ad1f3a447c2 100644 --- a/mysql-test/suite/innodb/r/check_ibd_filesize,32k.rdiff +++ b/mysql-test/suite/innodb/r/check_ibd_filesize,32k.rdiff @@ -1,5 +1,5 @@ ---- mysql-test/suite/innodb/r/check_ibd_filesize.result 2022-08-16 17:28:06.462350465 +0530 -+++ mysql-test/suite/innodb/r/check_ibd_filesize.reject 2022-08-16 17:29:25.129637040 +0530 +--- mysql-test/suite/innodb/r/check_ibd_filesize.result ++++ mysql-test/suite/innodb/r/check_ibd_filesize.reject @@ -3,18 +3,12 @@ # SPACE IN 5.7 THAN IN 5.6 # @@ -14,7 +14,7 @@ -# bytes: 65536 +# bytes: 131072 INSERT INTO t1 SELECT seq,REPEAT('a',30000) FROM seq_1_to_20; --# bytes: 4194304 +-# bytes: 2097152 -DROP TABLE t1; -CREATE TABLE t1 (a INT PRIMARY KEY, b BLOB) -ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; diff --git a/mysql-test/suite/innodb/r/check_ibd_filesize,4k.rdiff b/mysql-test/suite/innodb/r/check_ibd_filesize,4k.rdiff index ef55ad971fe..1412df393ff 100644 --- a/mysql-test/suite/innodb/r/check_ibd_filesize,4k.rdiff +++ b/mysql-test/suite/innodb/r/check_ibd_filesize,4k.rdiff @@ -1,5 +1,5 @@ ---- mysql-test/suite/innodb/r/check_ibd_filesize.result 2022-08-16 17:28:06.462350465 +0530 -+++ mysql-test/suite/innodb/r/check_ibd_filesize.reject 2022-08-16 17:31:39.288769153 +0530 +--- mysql-test/suite/innodb/r/check_ibd_filesize.result ++++ mysql-test/suite/innodb/r/check_ibd_filesize.reject @@ -3,18 +3,18 @@ # SPACE IN 5.7 THAN IN 5.6 # @@ -13,7 +13,7 @@ -# bytes: 65536 +# bytes: 16384 INSERT INTO t1 SELECT seq,REPEAT('a',30000) FROM seq_1_to_20; - # bytes: 4194304 + # bytes: 2097152 DROP TABLE t1; CREATE TABLE t1 (a INT PRIMARY KEY, b BLOB) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; diff --git a/mysql-test/suite/innodb/r/check_ibd_filesize,64k.rdiff b/mysql-test/suite/innodb/r/check_ibd_filesize,64k.rdiff index bcdcea31160..156925597ab 100644 --- a/mysql-test/suite/innodb/r/check_ibd_filesize,64k.rdiff +++ b/mysql-test/suite/innodb/r/check_ibd_filesize,64k.rdiff @@ -1,5 +1,5 @@ ---- mysql-test/suite/innodb/r/check_ibd_filesize.result 2022-08-16 17:28:06.462350465 +0530 -+++ mysql-test/suite/innodb/r/check_ibd_filesize.reject 2022-08-16 17:30:28.957174270 +0530 +--- mysql-test/suite/innodb/r/check_ibd_filesize.result ++++ mysql-test/suite/innodb/r/check_ibd_filesize.reject @@ -3,18 +3,12 @@ # SPACE IN 5.7 THAN IN 5.6 # @@ -14,7 +14,7 @@ -# bytes: 65536 +# bytes: 262144 INSERT INTO t1 SELECT seq,REPEAT('a',30000) FROM seq_1_to_20; --# bytes: 4194304 +-# bytes: 2097152 -DROP TABLE t1; -CREATE TABLE t1 (a INT PRIMARY KEY, b BLOB) -ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; diff --git a/mysql-test/suite/innodb/r/check_ibd_filesize,8k.rdiff b/mysql-test/suite/innodb/r/check_ibd_filesize,8k.rdiff index 7b699ef4cea..55cf59737d3 100644 --- a/mysql-test/suite/innodb/r/check_ibd_filesize,8k.rdiff +++ b/mysql-test/suite/innodb/r/check_ibd_filesize,8k.rdiff @@ -1,5 +1,5 @@ ---- mysql-test/suite/innodb/r/check_ibd_filesize.result 2022-08-16 17:28:06.462350465 +0530 -+++ mysql-test/suite/innodb/r/check_ibd_filesize.reject 2022-08-16 17:31:03.516962339 +0530 +--- mysql-test/suite/innodb/r/check_ibd_filesize.result ++++ mysql-test/suite/innodb/r/check_ibd_filesize.reject @@ -3,18 +3,18 @@ # SPACE IN 5.7 THAN IN 5.6 # @@ -13,7 +13,7 @@ -# bytes: 65536 +# bytes: 32768 INSERT INTO t1 SELECT seq,REPEAT('a',30000) FROM seq_1_to_20; - # bytes: 4194304 + # bytes: 2097152 DROP TABLE t1; CREATE TABLE t1 (a INT PRIMARY KEY, b BLOB) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; diff --git a/mysql-test/suite/innodb/r/check_ibd_filesize.result b/mysql-test/suite/innodb/r/check_ibd_filesize.result index 0d224d6ac5f..b0f376183ea 100644 --- a/mysql-test/suite/innodb/r/check_ibd_filesize.result +++ b/mysql-test/suite/innodb/r/check_ibd_filesize.result @@ -10,7 +10,7 @@ DROP TABLE t1; CREATE TABLE t1 (a INT PRIMARY KEY, b BLOB) ENGINE=InnoDB; # bytes: 65536 INSERT INTO t1 SELECT seq,REPEAT('a',30000) FROM seq_1_to_20; -# bytes: 4194304 +# bytes: 2097152 DROP TABLE t1; CREATE TABLE t1 (a INT PRIMARY KEY, b BLOB) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; diff --git a/mysql-test/suite/innodb/r/cursor-restore-unique-null.result b/mysql-test/suite/innodb/r/cursor-restore-unique-null.result new file mode 100644 index 00000000000..29edc47a483 --- /dev/null +++ b/mysql-test/suite/innodb/r/cursor-restore-unique-null.result @@ -0,0 +1,24 @@ +CREATE TABLE t(a INT PRIMARY KEY, b INT, c INT, UNIQUE KEY `b_c` (`b`,`c`)) +ENGINE=InnoDB, STATS_PERSISTENT=0; +INSERT INTO t SET a = 1, c = 2; +connect con1,localhost,root; +BEGIN; +INSERT INTO t SET a=2, c=2; +connection default; +BEGIN; +SET DEBUG_SYNC="lock_wait_start SIGNAL select_locked"; +SELECT * FROM t FORCE INDEX(b) FOR UPDATE; +connection con1; +SET DEBUG_SYNC="now WAIT_FOR select_locked"; +ROLLBACK; +connection default; +# If the bug is not fixed, and the both unique index key fields are +# NULL, there will be two (1, NULL, 2) rows in the result, +# because cursor will be restored to (NULL, 2, 1) position for +# secondary key instead of "supremum". +a b c +1 NULL 2 +COMMIT; +SET DEBUG_SYNC="RESET"; +disconnect con1; +DROP TABLE t; diff --git a/mysql-test/suite/innodb/r/instant_alter_extend.result b/mysql-test/suite/innodb/r/instant_alter_extend.result index 33a5f57c7b6..c22043eceb1 100644 Binary files a/mysql-test/suite/innodb/r/instant_alter_extend.result and b/mysql-test/suite/innodb/r/instant_alter_extend.result differ diff --git a/mysql-test/suite/innodb/r/instant_alter_import.result b/mysql-test/suite/innodb/r/instant_alter_import.result index 3e7ee35fdc1..6fe48fb6fab 100644 --- a/mysql-test/suite/innodb/r/instant_alter_import.result +++ b/mysql-test/suite/innodb/r/instant_alter_import.result @@ -64,6 +64,7 @@ alter table t1 discard tablespace; flush tables t2 for export; unlock tables; alter table t1 import tablespace; +# restart select * from t1; z 42 diff --git a/mysql-test/suite/innodb/r/lock_isolation.result b/mysql-test/suite/innodb/r/lock_isolation.result index 88a2ad9326e..31843266617 100644 --- a/mysql-test/suite/innodb/r/lock_isolation.result +++ b/mysql-test/suite/innodb/r/lock_isolation.result @@ -82,7 +82,6 @@ SELECT * FROM t; a b 10 20 10 20 -disconnect consistent; connection default; TRUNCATE TABLE t; INSERT INTO t VALUES(NULL, 1), (2, 2); @@ -99,10 +98,39 @@ a b COMMIT; connection con_weird; COMMIT; -disconnect con_weird; connection default; SELECT * FROM t; a b 10 1 10 20 DROP TABLE t; +# +# MDEV-33802 Weird read view after ROLLBACK of other transactions +# +CREATE TABLE t(a INT PRIMARY KEY, b INT UNIQUE) ENGINE=InnoDB; +INSERT INTO t SET a=1; +BEGIN; +INSERT INTO t SET a=2; +connection consistent; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +SELECT * FROM t FORCE INDEX (b) FOR UPDATE; +ERROR HY000: Record has changed since last read in table 't' +connection con_weird; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +SELECT * FROM t FORCE INDEX (b) FOR UPDATE; +connection default; +ROLLBACK; +connection con_weird; +a b +1 NULL +SELECT * FROM t FORCE INDEX (b) FOR UPDATE; +a b +1 NULL +disconnect con_weird; +connection consistent; +SELECT * FROM t FORCE INDEX (b) FOR UPDATE; +a b +1 NULL +disconnect consistent; +connection default; +DROP TABLE t; diff --git a/mysql-test/suite/innodb/r/monitor.result b/mysql-test/suite/innodb/r/monitor.result index 66a500ac8a5..1834032e9fb 100644 --- a/mysql-test/suite/innodb/r/monitor.result +++ b/mysql-test/suite/innodb/r/monitor.result @@ -196,6 +196,7 @@ icp_attempts disabled icp_no_match disabled icp_out_of_range disabled icp_match disabled +create temporary table orig_innodb_metrics as select name, enabled from information_schema.innodb_metrics; set global innodb_monitor_disable = All; select name from information_schema.innodb_metrics where enabled; name @@ -429,7 +430,7 @@ set global innodb_monitor_reset_all = default; # MONITORS # CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB STATS_PERSISTENT=0; -SELECT NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME +SELECT /*1*/ NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE 'buffer_page_written_index_leaf'; NAME COUNT > 0 buffer_page_written_index_leaf 0 @@ -437,13 +438,13 @@ SET GLOBAL innodb_monitor_enable='module_buffer_page'; INSERT INTO t1 VALUES (1), (2), (3), (4); FLUSH TABLES t1 FOR EXPORT; UNLOCK TABLES; -SELECT NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME +SELECT /*2*/ NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE 'buffer_page_written_index_leaf'; NAME COUNT > 0 buffer_page_written_index_leaf 1 SET GLOBAL innodb_monitor_disable='module_buffer_page'; SET GLOBAL innodb_monitor_reset_all='module_buffer_page'; -SELECT NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME +SELECT /*3*/ NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE 'buffer_page_written_index_leaf'; NAME COUNT > 0 buffer_page_written_index_leaf 0 @@ -453,13 +454,13 @@ ERROR 42000: Variable 'innodb_compression_algorithm' can't be set to the value o INSERT INTO t1 VALUES (5), (6), (7), (8); FLUSH TABLES t1 FOR EXPORT; UNLOCK TABLES; -SELECT NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME +SELECT /*4*/ NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE 'buffer_page_written_index_leaf'; NAME COUNT > 0 buffer_page_written_index_leaf 1 SET GLOBAL innodb_monitor_disable='%'; SET GLOBAL innodb_monitor_reset_all='%'; -SELECT NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME +SELECT /*5*/ NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE 'buffer_page_written_index_leaf'; NAME COUNT > 0 buffer_page_written_index_leaf 0 @@ -467,7 +468,7 @@ SET GLOBAL innodb_monitor_enable='ALL'; INSERT INTO t1 VALUES (9), (10), (11), (12); FLUSH TABLES t1 FOR EXPORT; UNLOCK TABLES; -SELECT NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME +SELECT /*6*/ NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE 'buffer_page_written_index_leaf'; NAME COUNT > 0 buffer_page_written_index_leaf 1 @@ -597,6 +598,41 @@ DROP TABLE t1; DROP TABLE fl2; DROP TABLE fl1; DROP TABLE fl0; -SET GLOBAL innodb_monitor_enable=default; -SET GLOBAL innodb_monitor_disable=default; -SET GLOBAL innodb_monitor_reset_all=default; +set global innodb_monitor_disable = 'adaptive\\_hash\\_p%'; +set global innodb_monitor_disable = 'adaptive\\_hash\\_r%'; +set global innodb_monitor_disable = 'buffer\\_LRU\\_batch\\_n%'; +set global innodb_monitor_disable = 'buffer\\_LRU\\_batch\\_s%'; +set global innodb_monitor_disable = 'buffer\\_LRU\\_g%'; +set global innodb_monitor_disable = 'buffer\\_LRU\\_s%'; +set global innodb_monitor_disable = 'buffer\\_LRU\\_u%'; +set global innodb_monitor_disable = 'buffer\\_f%'; +set global innodb_monitor_disable = 'buffer\\_page\\_%'; +set global innodb_monitor_disable = 'c%'; +set global innodb_monitor_disable = 'ddl%'; +set global innodb_monitor_disable = 'icp%'; +set global innodb_monitor_disable = 'index\\_p%'; +set global innodb_monitor_disable = 'innodb\\_di%'; +set global innodb_monitor_disable = 'innodb\\_l%'; +set global innodb_monitor_disable = 'innodb\\_m%'; +set global innodb_monitor_disable = 'lock\\_re%'; +set global innodb_monitor_disable = 'lock\\_ta%'; +set global innodb_monitor_disable = 'log%'; +set global innodb_monitor_disable = 'm%'; +set global innodb_monitor_disable = 'p%'; +set global innodb_monitor_disable = 't%'; +set global innodb_monitor_enable = 'log\\_w%'; +set global innodb_monitor_enable = 'trx_rseg_history_len'; +set global innodb_monitor_enable = 'trx_undo_slots_cached'; +set global innodb_monitor_enable=default; +Warnings: +Warning 1230 Default value is not defined for this set option. Please specify correct counter or module name. +set global innodb_monitor_disable=default; +Warnings: +Warning 1230 Default value is not defined for this set option. Please specify correct counter or module name. +set global innodb_monitor_reset_all=default; +Warnings: +Warning 1230 Default value is not defined for this set option. Please specify correct counter or module name. +select name, orig.enabled, new.enabled from +orig_innodb_metrics orig join information_schema.innodb_metrics new using(name) +where orig.enabled != new.enabled; +name enabled enabled diff --git a/mysql-test/suite/innodb/t/alter_crash.test b/mysql-test/suite/innodb/t/alter_crash.test index 164ff877b62..f56dcf2c275 100644 --- a/mysql-test/suite/innodb/t/alter_crash.test +++ b/mysql-test/suite/innodb/t/alter_crash.test @@ -70,7 +70,7 @@ let $orig_table_id = `SELECT table_id WHERE name = 'test/t1'`; # Write file to make mysql-test-run.pl expect crash ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --error 2013 ALTER TABLE t1 ADD PRIMARY KEY (f2, f1); @@ -110,7 +110,7 @@ let $orig_table_id = `SELECT table_id WHERE name = 'test/t2'`; # Write file to make mysql-test-run.pl expect crash ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --error 2013 ALTER TABLE t2 ADD PRIMARY KEY (f2, f1); @@ -150,7 +150,7 @@ let $orig_table_id = `select table_id from information_schema.innodb_sys_tables where name = 'test/t1'`; # Write file to make mysql-test-run.pl expect crash ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect # --error 2013 ALTER TABLE t1 ADD INDEX (b), CHANGE c d int, ALGORITHM=INPLACE; diff --git a/mysql-test/suite/innodb/t/alter_rename_existing.test b/mysql-test/suite/innodb/t/alter_rename_existing.test index 556d8e660b4..f09456e747a 100644 --- a/mysql-test/suite/innodb/t/alter_rename_existing.test +++ b/mysql-test/suite/innodb/t/alter_rename_existing.test @@ -18,7 +18,7 @@ INSERT INTO t1(b) VALUES('one'), ('two'), ('three'); --echo # --echo # Create a file called MYSQLD_DATADIR/test/t1.ibd ---exec echo "This is not t1.ibd" > $MYSQLD_DATADIR/test/t1.ibd +--write_line "This is not t1.ibd" $MYSQLD_DATADIR/test/t1.ibd --echo # Directory listing of test/*.ibd --echo # diff --git a/mysql-test/suite/innodb/t/cursor-restore-unique-null.test b/mysql-test/suite/innodb/t/cursor-restore-unique-null.test new file mode 100644 index 00000000000..409694d695b --- /dev/null +++ b/mysql-test/suite/innodb/t/cursor-restore-unique-null.test @@ -0,0 +1,36 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +--source include/count_sessions.inc + + +CREATE TABLE t(a INT PRIMARY KEY, b INT, c INT, UNIQUE KEY `b_c` (`b`,`c`)) + ENGINE=InnoDB, STATS_PERSISTENT=0; +INSERT INTO t SET a = 1, c = 2; + +--connect con1,localhost,root +BEGIN; + INSERT INTO t SET a=2, c=2; + +--connection default +BEGIN; +SET DEBUG_SYNC="lock_wait_start SIGNAL select_locked"; +--send SELECT * FROM t FORCE INDEX(b) FOR UPDATE + +--connection con1 +SET DEBUG_SYNC="now WAIT_FOR select_locked"; +ROLLBACK; + +--connection default +--echo # If the bug is not fixed, and the both unique index key fields are +--echo # NULL, there will be two (1, NULL, 2) rows in the result, +--echo # because cursor will be restored to (NULL, 2, 1) position for +--echo # secondary key instead of "supremum". +--reap +COMMIT; + +SET DEBUG_SYNC="RESET"; + +--disconnect con1 +DROP TABLE t; +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb/t/doublewrite_debug.test b/mysql-test/suite/innodb/t/doublewrite_debug.test index ab7fd8eba22..b8dcd5068ef 100644 --- a/mysql-test/suite/innodb/t/doublewrite_debug.test +++ b/mysql-test/suite/innodb/t/doublewrite_debug.test @@ -45,7 +45,7 @@ commit work; # 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"; +let $restart_parameters=--debug_dbug=+d,ib_log_checkpoint_avoid_hard --innodb_flush_sync=0; --source include/restart_mysqld.inc --source ../include/no_checkpoint_start.inc begin; @@ -95,7 +95,7 @@ select f1, f2 from t1; --echo # Test Begin: Test if recovery works if 1st page of --echo # system tablespace is corrupted and 2nd page as corrupted. -let $restart_parameters="--debug_dbug=+d,ib_log_checkpoint_avoid_hard --innodb_flush_sync=0"; +let $restart_parameters=--debug_dbug=+d,ib_log_checkpoint_avoid_hard --innodb_flush_sync=0; --source include/restart_mysqld.inc --source ../include/no_checkpoint_start.inc begin; diff --git a/mysql-test/suite/innodb/t/group_commit_crash.test b/mysql-test/suite/innodb/t/group_commit_crash.test index 12f7ba202e3..b0ed854f4f3 100644 --- a/mysql-test/suite/innodb/t/group_commit_crash.test +++ b/mysql-test/suite/innodb/t/group_commit_crash.test @@ -51,7 +51,7 @@ while ($numtests) START TRANSACTION; insert into t1 select * from t2; # Write file to make mysql-test-run.pl expect crash - --exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect eval call setcrash($numtests); diff --git a/mysql-test/suite/innodb/t/group_commit_crash_no_optimize_thread.test b/mysql-test/suite/innodb/t/group_commit_crash_no_optimize_thread.test index 6115e3f0050..9b7de7cea56 100644 --- a/mysql-test/suite/innodb/t/group_commit_crash_no_optimize_thread.test +++ b/mysql-test/suite/innodb/t/group_commit_crash_no_optimize_thread.test @@ -51,7 +51,7 @@ while ($numtests) START TRANSACTION; insert into t1 select * from t2; # Write file to make mysql-test-run.pl expect crash - --exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + --write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect eval call setcrash($numtests); diff --git a/mysql-test/suite/innodb/t/innodb-alter-tempfile.test b/mysql-test/suite/innodb/t/innodb-alter-tempfile.test index 2534f03dbec..0b6cbabb802 100644 --- a/mysql-test/suite/innodb/t/innodb-alter-tempfile.test +++ b/mysql-test/suite/innodb/t/innodb-alter-tempfile.test @@ -35,7 +35,7 @@ let datadir= `select @@datadir`; CREATE TABLE t1 (f1 INT NOT NULL, f2 INT NOT NULL) ENGINE=innodb; SET debug_dbug='+d,innodb_alter_commit_crash_before_commit'; ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --error 2013 ALTER TABLE t1 ADD PRIMARY KEY (f2, f1); diff --git a/mysql-test/suite/innodb/t/innodb-corrupted-table.test b/mysql-test/suite/innodb/t/innodb-corrupted-table.test index a064f08d677..dcdaa61859f 100644 --- a/mysql-test/suite/innodb/t/innodb-corrupted-table.test +++ b/mysql-test/suite/innodb/t/innodb-corrupted-table.test @@ -23,14 +23,14 @@ alter table t1 add primary key (pk); --echo # Stop the server, replace the frm with the old one and restart the server ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --shutdown_server --source include/wait_until_disconnected.inc --remove_file $datadir/test/t1.frm --copy_file $MYSQLTEST_VARDIR/tmp/t1.frm $datadir/test/t1.frm ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --enable_reconnect --source include/wait_until_connected_again.inc diff --git a/mysql-test/suite/innodb/t/innodb-wl5522-debug.test b/mysql-test/suite/innodb/t/innodb-wl5522-debug.test index e642a9491fe..2d3b5b3fae4 100644 --- a/mysql-test/suite/innodb/t/innodb-wl5522-debug.test +++ b/mysql-test/suite/innodb/t/innodb-wl5522-debug.test @@ -43,7 +43,7 @@ INSERT INTO t1 VALUES(1),(2),(3); --let $_expect_file_name= `select regexp_replace(@@tmpdir, '^.*/','')` --let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/$_expect_file_name.expect ---exec echo wait > $_expect_file_name +--write_line wait $_expect_file_name SET SESSION debug_dbug="+d,ib_discard_before_commit_crash"; --error 2013 ALTER TABLE t1 DISCARD TABLESPACE; @@ -57,7 +57,7 @@ SET GLOBAL innodb_file_per_table = 1; CREATE TABLE t1 (c1 INT) ENGINE = InnoDB; INSERT INTO t1 VALUES(1),(2),(3); ---exec echo wait > $_expect_file_name +--write_line wait $_expect_file_name SET SESSION debug_dbug="+d,ib_discard_after_commit_crash"; --error 2013 ALTER TABLE t1 DISCARD TABLESPACE; @@ -101,7 +101,7 @@ EOF --error ER_TABLESPACE_DISCARDED SELECT * FROM t1; ---exec echo wait > $_expect_file_name +--write_line wait $_expect_file_name SET SESSION debug_dbug="+d,ib_import_before_commit_crash"; --error 2013 ALTER TABLE t1 IMPORT TABLESPACE; diff --git a/mysql-test/suite/innodb/t/innodb_bug60196.test b/mysql-test/suite/innodb/t/innodb_bug60196.test index 7f1f5c40585..41b9a4d8476 100644 --- a/mysql-test/suite/innodb/t/innodb_bug60196.test +++ b/mysql-test/suite/innodb/t/innodb_bug60196.test @@ -58,7 +58,7 @@ SELECT * FROM bug_60196; --echo # Restart server. # Write file to make mysql-test-run.pl start up the server again ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect # Turn on reconnect --enable_reconnect @@ -132,7 +132,7 @@ SELECT * FROM Bug_60309; --echo # Restart server. # Write file to make mysql-test-run.pl start up the server again ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect # Turn on reconnect --enable_reconnect diff --git a/mysql-test/suite/innodb/t/innodb_defrag_stats.test b/mysql-test/suite/innodb/t/innodb_defrag_stats.test index ef79d8d6ade..3730eb657af 100644 --- a/mysql-test/suite/innodb/t/innodb_defrag_stats.test +++ b/mysql-test/suite/innodb/t/innodb_defrag_stats.test @@ -35,7 +35,7 @@ SELECT @@GLOBAL.innodb_force_recovery<2 "have background defragmentation"; # Wait for defrag_pool to be processed. let $wait_timeout=30; -let $wait_condition = SELECT COUNT(*)>0 FROM mysql.innodb_index_stats; +let $wait_condition = SELECT COUNT(*)>5 FROM mysql.innodb_index_stats; --source include/wait_condition.inc --sorted_result diff --git a/mysql-test/suite/innodb/t/instant_alter_extend.test b/mysql-test/suite/innodb/t/instant_alter_extend.test index 7258ba6d238..636527e598c 100644 --- a/mysql-test/suite/innodb/t/instant_alter_extend.test +++ b/mysql-test/suite/innodb/t/instant_alter_extend.test @@ -256,3 +256,16 @@ select * from t1; check table t1; drop database best; + +--echo # +--echo # MDEV-33214 Table is getting rebuild with +--echo # ALTER TABLE ADD COLUMN +--echo # +use test; +CREATE TABLE t1(f1 INT, f2 VARCHAR(10)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; +INSERT INTO t1 VALUES(1,'abc'),(2,'def'); +ALTER TABLE t1 ADD (f3 VARCHAR(5000), f4 VARCHAR(20)), ALGORITHM=instant; +ALTER TABLE t1 ADD f5 TEXT, ALGORITHM=INSTANT; +DROP TABLE t1; + +--echo # End of 10.4 tests diff --git a/mysql-test/suite/innodb/t/instant_alter_import.test b/mysql-test/suite/innodb/t/instant_alter_import.test index 3a811def170..fa35c582633 100644 --- a/mysql-test/suite/innodb/t/instant_alter_import.test +++ b/mysql-test/suite/innodb/t/instant_alter_import.test @@ -83,6 +83,7 @@ flush tables t2 for export; unlock tables; alter table t1 import tablespace; +--source include/restart_mysqld.inc select * from t1; --remove_file $MYSQLD_DATADIR/test/t1.ibd diff --git a/mysql-test/suite/innodb/t/lock_isolation.test b/mysql-test/suite/innodb/t/lock_isolation.test index 30d2978f4f2..5c60f6e707c 100644 --- a/mysql-test/suite/innodb/t/lock_isolation.test +++ b/mysql-test/suite/innodb/t/lock_isolation.test @@ -79,7 +79,6 @@ COMMIT; --connection consistent --reap SELECT * FROM t; ---disconnect consistent --connection default TRUNCATE TABLE t; @@ -103,8 +102,48 @@ COMMIT; --connection con_weird --reap COMMIT; ---disconnect con_weird --connection default SELECT * FROM t; DROP TABLE t; + +--echo # +--echo # MDEV-33802 Weird read view after ROLLBACK of other transactions +--echo # + +CREATE TABLE t(a INT PRIMARY KEY, b INT UNIQUE) ENGINE=InnoDB; +INSERT INTO t SET a=1; + +BEGIN; INSERT INTO t SET a=2; + +--connection consistent +START TRANSACTION WITH CONSISTENT SNAPSHOT; +--disable_ps2_protocol +--error ER_CHECKREAD +SELECT * FROM t FORCE INDEX (b) FOR UPDATE; +--enable_ps2_protocol + +--connection con_weird +START TRANSACTION WITH CONSISTENT SNAPSHOT; +send +SELECT * FROM t FORCE INDEX (b) FOR UPDATE; + +--connection default +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = 'Sending data' + and info LIKE 'SELECT * FROM t %'; +--source include/wait_condition.inc +ROLLBACK; + +--connection con_weird +--reap +SELECT * FROM t FORCE INDEX (b) FOR UPDATE; +--disconnect con_weird + +--connection consistent +SELECT * FROM t FORCE INDEX (b) FOR UPDATE; +--disconnect consistent + +--connection default +DROP TABLE t; diff --git a/mysql-test/suite/innodb/t/log_file_name.test b/mysql-test/suite/innodb/t/log_file_name.test index f88a13db2e9..371d10c9468 100644 --- a/mysql-test/suite/innodb/t/log_file_name.test +++ b/mysql-test/suite/innodb/t/log_file_name.test @@ -206,7 +206,7 @@ print FILE "\0" x 16384; close(FILE); EOF ---exec echo "" > $MYSQLD_DATADIR/test/u2.ibd +--write_line "" $MYSQLD_DATADIR/test/u2.ibd --copy_file $MYSQLD_DATADIR/test/u6.ibd $MYSQLD_DATADIR/test/u4.ibd diff --git a/mysql-test/suite/innodb/t/monitor.test b/mysql-test/suite/innodb/t/monitor.test index 77483d62387..69545c9c6fc 100644 --- a/mysql-test/suite/innodb/t/monitor.test +++ b/mysql-test/suite/innodb/t/monitor.test @@ -5,11 +5,11 @@ # sys_vars.innodb_monitor_enable_basic --source include/have_innodb.inc -# Test turn on/off the monitor counter with "all" option -# By default, they will be off. select name, if(enabled,'enabled','disabled') status from information_schema.innodb_metrics; +create temporary table orig_innodb_metrics as select name, enabled from information_schema.innodb_metrics; + set global innodb_monitor_disable = All; select name from information_schema.innodb_metrics where enabled; @@ -315,18 +315,22 @@ CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB STATS_PERSISTENT=0; let $innodb_monitor_enable = `SELECT @@innodb_monitor_enable`; -SELECT NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME +SELECT /*1*/ NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE 'buffer_page_written_index_leaf'; SET GLOBAL innodb_monitor_enable='module_buffer_page'; INSERT INTO t1 VALUES (1), (2), (3), (4); FLUSH TABLES t1 FOR EXPORT; UNLOCK TABLES; -SELECT NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME + +let $wait_condition= select count > 0 from information_schema.innodb_metrics where name like 'buffer_page_written_index_leaf'; +source include/wait_condition.inc; + +SELECT /*2*/ NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE 'buffer_page_written_index_leaf'; SET GLOBAL innodb_monitor_disable='module_buffer_page'; SET GLOBAL innodb_monitor_reset_all='module_buffer_page'; -SELECT NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME +SELECT /*3*/ NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE 'buffer_page_written_index_leaf'; SET GLOBAL innodb_monitor_enable='%'; @@ -334,18 +338,22 @@ SET GLOBAL innodb_monitor_enable='%'; SET GLOBAL innodb_monitor_reset_all= '%', innodb_compression_algorithm= foo; INSERT INTO t1 VALUES (5), (6), (7), (8); FLUSH TABLES t1 FOR EXPORT; UNLOCK TABLES; -SELECT NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME + +let $wait_condition= select count > 0 from information_schema.innodb_metrics where name like 'buffer_page_written_index_leaf'; +source include/wait_condition.inc; + +SELECT /*4*/ NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE 'buffer_page_written_index_leaf'; SET GLOBAL innodb_monitor_disable='%'; SET GLOBAL innodb_monitor_reset_all='%'; -SELECT NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME +SELECT /*5*/ NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE 'buffer_page_written_index_leaf'; SET GLOBAL innodb_monitor_enable='ALL'; INSERT INTO t1 VALUES (9), (10), (11), (12); FLUSH TABLES t1 FOR EXPORT; UNLOCK TABLES; -SELECT NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME +SELECT /*6*/ NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE 'buffer_page_written_index_leaf'; DROP TABLE t1; @@ -462,8 +470,36 @@ DROP TABLE fl2; DROP TABLE fl1; DROP TABLE fl0; ---disable_warnings -SET GLOBAL innodb_monitor_enable=default; -SET GLOBAL innodb_monitor_disable=default; -SET GLOBAL innodb_monitor_reset_all=default; ---enable_warnings +set global innodb_monitor_disable = 'adaptive\\_hash\\_p%'; +set global innodb_monitor_disable = 'adaptive\\_hash\\_r%'; +set global innodb_monitor_disable = 'buffer\\_LRU\\_batch\\_n%'; +set global innodb_monitor_disable = 'buffer\\_LRU\\_batch\\_s%'; +set global innodb_monitor_disable = 'buffer\\_LRU\\_g%'; +set global innodb_monitor_disable = 'buffer\\_LRU\\_s%'; +set global innodb_monitor_disable = 'buffer\\_LRU\\_u%'; +set global innodb_monitor_disable = 'buffer\\_f%'; +set global innodb_monitor_disable = 'buffer\\_page\\_%'; +set global innodb_monitor_disable = 'c%'; +set global innodb_monitor_disable = 'ddl%'; +set global innodb_monitor_disable = 'icp%'; +set global innodb_monitor_disable = 'index\\_p%'; +set global innodb_monitor_disable = 'innodb\\_di%'; +set global innodb_monitor_disable = 'innodb\\_l%'; +set global innodb_monitor_disable = 'innodb\\_m%'; +set global innodb_monitor_disable = 'lock\\_re%'; +set global innodb_monitor_disable = 'lock\\_ta%'; +set global innodb_monitor_disable = 'log%'; +set global innodb_monitor_disable = 'm%'; +set global innodb_monitor_disable = 'p%'; +set global innodb_monitor_disable = 't%'; +set global innodb_monitor_enable = 'log\\_w%'; +set global innodb_monitor_enable = 'trx_rseg_history_len'; +set global innodb_monitor_enable = 'trx_undo_slots_cached'; + +set global innodb_monitor_enable=default; +set global innodb_monitor_disable=default; +set global innodb_monitor_reset_all=default; + +select name, orig.enabled, new.enabled from + orig_innodb_metrics orig join information_schema.innodb_metrics new using(name) + where orig.enabled != new.enabled; diff --git a/mysql-test/suite/innodb/t/temporary_table.test b/mysql-test/suite/innodb/t/temporary_table.test index b09ff7c7c30..ee1474bbab1 100644 --- a/mysql-test/suite/innodb/t/temporary_table.test +++ b/mysql-test/suite/innodb/t/temporary_table.test @@ -135,7 +135,7 @@ AND support IN ('YES', 'DEFAULT', 'ENABLED'); # We cannot use include/restart_mysqld.inc in this particular test, # because SHOW STATUS would fail due to unwritable (nonexistent) tmpdir. --source include/shutdown_mysqld.inc ---exec echo "restart: --tmpdir=/dev/null/$MYSQL_TMP_DIR --skip-innodb-fast-shutdown" > $_expect_file_name +--write_line "restart: --tmpdir=/dev/null/$MYSQL_TMP_DIR --skip-innodb-fast-shutdown" $_expect_file_name --enable_reconnect --disable_result_log --disable_query_log diff --git a/mysql-test/suite/innodb/t/undo_space_dblwr.test b/mysql-test/suite/innodb/t/undo_space_dblwr.test index 3f61e91ddf5..52b19a4b7fb 100644 --- a/mysql-test/suite/innodb/t/undo_space_dblwr.test +++ b/mysql-test/suite/innodb/t/undo_space_dblwr.test @@ -12,7 +12,7 @@ insert into t1 values (1, 1); # 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"; +let $restart_parameters=--debug_dbug=+d,ib_log_checkpoint_avoid_hard --innodb_flush_sync=0; --source include/restart_mysqld.inc --source ../include/no_checkpoint_start.inc diff --git a/mysql-test/suite/innodb/t/undo_truncate.test b/mysql-test/suite/innodb/t/undo_truncate.test index 4550e06bce8..9abf08ff436 100644 --- a/mysql-test/suite/innodb/t/undo_truncate.test +++ b/mysql-test/suite/innodb/t/undo_truncate.test @@ -13,7 +13,7 @@ call mtr.add_suppression("InnoDB: Trying to delete tablespace.*pending operation # Re-create the undo log tablespaces after slow shutdown SET GLOBAL innodb_fast_shutdown=0; -let $restart_parameters="--innodb_undo_tablespaces=2"; +let $restart_parameters=--innodb_undo_tablespaces=2; --source include/restart_mysqld.inc SET GLOBAL innodb_undo_log_truncate = 0; diff --git a/mysql-test/suite/innodb/t/undo_truncate_recover.test b/mysql-test/suite/innodb/t/undo_truncate_recover.test index 148c3f939d0..988b28f75b4 100644 --- a/mysql-test/suite/innodb/t/undo_truncate_recover.test +++ b/mysql-test/suite/innodb/t/undo_truncate_recover.test @@ -13,7 +13,7 @@ # Re-create the undo log tablespaces after slow shutdown SET GLOBAL innodb_fast_shutdown=0; -let $restart_parameters="--innodb_undo_tablespaces=2"; +let $restart_parameters=--innodb_undo_tablespaces=2; --source include/restart_mysqld.inc SET GLOBAL innodb_undo_log_truncate = 1; diff --git a/mysql-test/suite/innodb_fts/t/sync.test b/mysql-test/suite/innodb_fts/t/sync.test index 168309a5c92..56b9052a47a 100644 --- a/mysql-test/suite/innodb_fts/t/sync.test +++ b/mysql-test/suite/innodb_fts/t/sync.test @@ -115,7 +115,7 @@ CREATE TABLE t1 ( INSERT INTO t1(title) VALUES('database'); ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect SET debug_dbug = '+d,fts_instrument_sync_debug,fts_write_node_crash'; diff --git a/mysql-test/suite/innodb_gis/t/rollback.test b/mysql-test/suite/innodb_gis/t/rollback.test index fcfe71e2f80..a09986692ee 100644 --- a/mysql-test/suite/innodb_gis/t/rollback.test +++ b/mysql-test/suite/innodb_gis/t/rollback.test @@ -463,7 +463,7 @@ rollback; # Test partial update rollback after recovered. # Crash the server in partial update. ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect set session debug="+d,row_mysql_crash_if_error"; --error 2013 update t1 set a=point(5,5), b=point(5,5), c=5 where i < 3; diff --git a/mysql-test/suite/innodb_zip/t/restart.test b/mysql-test/suite/innodb_zip/t/restart.test index c442b919d71..0c8073b8200 100644 --- a/mysql-test/suite/innodb_zip/t/restart.test +++ b/mysql-test/suite/innodb_zip/t/restart.test @@ -412,13 +412,13 @@ SHOW CREATE TABLE t77_restart; --echo # Moving tablespace 't4_restart' from MYSQL_DATA_DIR to MYSQL_TMP_DIR/new_dir --copy_file $MYSQL_DATA_DIR/test/t4_restart.ibd $MYSQL_TMP_DIR/new_dir/test/t4_restart.ibd --remove_file $MYSQL_DATA_DIR/test/t4_restart.ibd ---exec echo $MYSQL_TMP_DIR/new_dir/test/t4_restart.ibd > $MYSQL_DATA_DIR/test/t4_restart.isl +--write_line $MYSQL_TMP_DIR/new_dir/test/t4_restart.ibd $MYSQL_DATA_DIR/test/t4_restart.isl --echo # Moving tablespace 't55_restart' from MYSQL_TMP_DIR/alt_dir to MYSQL_TMP_DIR/new_dir --copy_file $MYSQL_TMP_DIR/alt_dir/test/t55_restart.ibd $MYSQL_TMP_DIR/new_dir/test/t55_restart.ibd --remove_file $MYSQL_TMP_DIR/alt_dir/test/t55_restart.ibd --remove_file $MYSQL_DATA_DIR/test/t55_restart.isl ---exec echo $MYSQL_TMP_DIR/new_dir/test/t55_restart.ibd > $MYSQL_DATA_DIR/test/t55_restart.isl +--write_line $MYSQL_TMP_DIR/new_dir/test/t55_restart.ibd $MYSQL_DATA_DIR/test/t55_restart.isl --echo # Moving tablespace 't66_restart' from MYSQL_TMP_DIR/alt_dir to MYSQL_TMP_DIR/new_dir --copy_file $MYSQL_TMP_DIR/alt_dir/test/t66_restart#P#p0.ibd $MYSQL_TMP_DIR/new_dir/test/t66_restart#P#p0.ibd @@ -430,9 +430,9 @@ SHOW CREATE TABLE t77_restart; --remove_file $MYSQL_DATA_DIR/test/t66_restart#P#p0.isl --remove_file $MYSQL_DATA_DIR/test/t66_restart#P#p1.isl --remove_file $MYSQL_DATA_DIR/test/t66_restart#P#p2.isl ---exec echo $MYSQL_TMP_DIR/new_dir/test/t66_restart#P#p0.ibd > $MYSQL_DATA_DIR/test/t66_restart#P#p0.isl ---exec echo $MYSQL_TMP_DIR/new_dir/test/t66_restart#P#p1.ibd > $MYSQL_DATA_DIR/test/t66_restart#P#p1.isl ---exec echo $MYSQL_TMP_DIR/new_dir/test/t66_restart#P#p2.ibd > $MYSQL_DATA_DIR/test/t66_restart#P#p2.isl +--write_line $MYSQL_TMP_DIR/new_dir/test/t66_restart#P#p0.ibd $MYSQL_DATA_DIR/test/t66_restart#P#p0.isl +--write_line $MYSQL_TMP_DIR/new_dir/test/t66_restart#P#p1.ibd $MYSQL_DATA_DIR/test/t66_restart#P#p1.isl +--write_line $MYSQL_TMP_DIR/new_dir/test/t66_restart#P#p2.ibd $MYSQL_DATA_DIR/test/t66_restart#P#p2.isl --echo # Moving tablespace 't77_restart' from MYSQL_TMP_DIR/alt_dir to MYSQL_TMP_DIR/new_dir --copy_file $MYSQL_TMP_DIR/alt_dir/test/t77_restart#P#p0#SP#s0.ibd $MYSQL_TMP_DIR/new_dir/test/t77_restart#P#p0#SP#s0.ibd @@ -447,10 +447,10 @@ SHOW CREATE TABLE t77_restart; --remove_file $MYSQL_DATA_DIR/test/t77_restart#P#p0#SP#s1.isl --remove_file $MYSQL_DATA_DIR/test/t77_restart#P#p1#SP#s2.isl --remove_file $MYSQL_DATA_DIR/test/t77_restart#P#p1#SP#s3.isl ---exec echo $MYSQL_TMP_DIR/new_dir/test/t77_restart#P#p0#SP#s0.ibd > $MYSQL_DATA_DIR/test/t77_restart#P#p0#SP#s0.isl ---exec echo $MYSQL_TMP_DIR/new_dir/test/t77_restart#P#p0#SP#s1.ibd > $MYSQL_DATA_DIR/test/t77_restart#P#p0#SP#s1.isl ---exec echo $MYSQL_TMP_DIR/new_dir/test/t77_restart#P#p1#SP#s2.ibd > $MYSQL_DATA_DIR/test/t77_restart#P#p1#SP#s2.isl ---exec echo $MYSQL_TMP_DIR/new_dir/test/t77_restart#P#p1#SP#s3.ibd > $MYSQL_DATA_DIR/test/t77_restart#P#p1#SP#s3.isl +--write_line $MYSQL_TMP_DIR/new_dir/test/t77_restart#P#p0#SP#s0.ibd $MYSQL_DATA_DIR/test/t77_restart#P#p0#SP#s0.isl +--write_line $MYSQL_TMP_DIR/new_dir/test/t77_restart#P#p0#SP#s1.ibd $MYSQL_DATA_DIR/test/t77_restart#P#p0#SP#s1.isl +--write_line $MYSQL_TMP_DIR/new_dir/test/t77_restart#P#p1#SP#s2.ibd $MYSQL_DATA_DIR/test/t77_restart#P#p1#SP#s2.isl +--write_line $MYSQL_TMP_DIR/new_dir/test/t77_restart#P#p1#SP#s3.ibd $MYSQL_DATA_DIR/test/t77_restart#P#p1#SP#s3.isl --echo ---- MYSQL_DATA_DIR/test --list_files_write_file $MYSQLD_DATADIR.files.txt $MYSQL_DATA_DIR/test diff --git a/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test b/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test index 36dcd1e454b..47b53b718f5 100644 --- a/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test +++ b/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test @@ -75,7 +75,7 @@ SET SESSION debug_dbug="+d,ib_import_before_commit_crash"; SELECT * FROM t1; # Write file to make mysql-test-run.pl start up the server again ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect # Execute the statement that causes the crash --error 2013 @@ -96,7 +96,7 @@ SET SESSION debug_dbug="+d,ib_import_before_checkpoint_crash"; SELECT COUNT(*) FROM t1; # Don't start up the server right away. ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect # Execute the statement that causes the crash --error 2013 @@ -113,7 +113,7 @@ EOF --echo # Restart and reconnect to the server --enable_reconnect ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --source include/wait_until_connected_again.inc --disable_reconnect diff --git a/mysql-test/suite/large_tests/t/maria_recover_encrypted.test b/mysql-test/suite/large_tests/t/maria_recover_encrypted.test index 4c590e5e1f9..1064c2c0884 100644 --- a/mysql-test/suite/large_tests/t/maria_recover_encrypted.test +++ b/mysql-test/suite/large_tests/t/maria_recover_encrypted.test @@ -3,6 +3,8 @@ --source include/have_maria.inc --source include/default_charset.inc +--source include/not_embedded.inc +--source include/have_debug.inc # Cleanup --disable_warnings @@ -13,7 +15,7 @@ DROP PROCEDURE IF EXISTS proc_insert_many; # -------- # Configure encryption ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --shutdown_server --source include/wait_until_disconnected.inc @@ -21,7 +23,7 @@ DROP PROCEDURE IF EXISTS proc_insert_many; 1;76025E3ADC78D74819927DB02AAA4C35 EOF ---exec echo "restart:--aria-encrypt-tables=1 --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/key.txt" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line "restart:--aria-encrypt-tables=1 --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/key.txt" $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --enable_reconnect --source include/wait_until_connected_again.inc @@ -73,7 +75,7 @@ CALL proc_insert_many(); UNLOCK TABLES; # Crash and restart the server while it's still flushing index ---exec echo "restart:--aria-encrypt-tables=1 --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/key.txt" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line "restart:--aria-encrypt-tables=1 --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/key.txt" $MYSQLTEST_VARDIR/tmp/mysqld.1.expect SET debug_dbug="d,crash_shutdown"; --error 2013 shutdown; diff --git a/mysql-test/suite/maria/bulk_insert_crash.test b/mysql-test/suite/maria/bulk_insert_crash.test index d9167c3f0d7..04f3a148ad4 100644 --- a/mysql-test/suite/maria/bulk_insert_crash.test +++ b/mysql-test/suite/maria/bulk_insert_crash.test @@ -12,7 +12,7 @@ # # Write file to make mysql-test-run.pl expect crash and restart ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect create table t1 (a int primary key, b int, c int, unique key(b), key(c)) engine=aria transactional=1; insert into t1 values (1000,1000,1000); diff --git a/mysql-test/suite/maria/encrypt-no-key.test b/mysql-test/suite/maria/encrypt-no-key.test index 457441226cc..e1d674097bf 100644 --- a/mysql-test/suite/maria/encrypt-no-key.test +++ b/mysql-test/suite/maria/encrypt-no-key.test @@ -29,10 +29,10 @@ CREATE TABLE t1 (a INT KEY,b INT,KEY(b)) ENGINE=Aria; --echo # Restart with encryption enabled ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --shutdown_server --source include/wait_until_disconnected.inc ---exec echo "restart:--aria-encrypt-tables=1 --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys1.txt" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line "restart:--aria-encrypt-tables=1 --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys1.txt" $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --enable_reconnect --source include/wait_until_connected_again.inc @@ -43,10 +43,10 @@ LOAD INDEX INTO CACHE t1; # Restart without encryption. Above table should be unreadable ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --shutdown_server --source include/wait_until_disconnected.inc ---exec echo "restart:--aria-encrypt-tables=0" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line "restart:--aria-encrypt-tables=0" $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --enable_reconnect --source include/wait_until_connected_again.inc diff --git a/mysql-test/suite/maria/encrypt-wrong-key.test b/mysql-test/suite/maria/encrypt-wrong-key.test index ac060c4e9dd..274a165ca4d 100644 --- a/mysql-test/suite/maria/encrypt-wrong-key.test +++ b/mysql-test/suite/maria/encrypt-wrong-key.test @@ -9,7 +9,7 @@ call mtr.add_suppression("System key id 1 is missing"); call mtr.add_suppression("Unknown key id 1"); call mtr.add_suppression("Initialization of encryption failed.*"); ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --shutdown_server --source include/wait_until_disconnected.inc @@ -17,14 +17,14 @@ call mtr.add_suppression("Initialization of encryption failed.*"); 1;770A8A65DA156D24EE2A093277530142 EOF ---exec echo "restart:--aria-encrypt-tables=1 --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys1.txt" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line "restart:--aria-encrypt-tables=1 --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys1.txt" $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --enable_reconnect --source include/wait_until_connected_again.inc CREATE TABLE t1 (i INT, KEY(i)) ENGINE=Aria; INSERT INTO t1 VALUES (1); ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --shutdown_server --source include/wait_until_disconnected.inc @@ -32,7 +32,7 @@ INSERT INTO t1 VALUES (1); 2;770A8A65DA156D24EE2A093277530143 EOF ---exec echo "restart:--aria-encrypt-tables=1 --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys2.txt" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line "restart:--aria-encrypt-tables=1 --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys2.txt" $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --enable_reconnect --source include/wait_until_connected_again.inc @@ -43,11 +43,11 @@ repair table t1; --error HA_ERR_NO_ENCRYPTION INSERT INTO t1 VALUES (2); ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --shutdown_server --source include/wait_until_disconnected.inc ---exec echo "restart:--aria-encrypt-tables=1 --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys1.txt" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line "restart:--aria-encrypt-tables=1 --plugin-load-add=file_key_management --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys1.txt" $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --enable_reconnect --source include/wait_until_connected_again.inc diff --git a/mysql-test/suite/multi_source/gtid_ignore_duplicates.result b/mysql-test/suite/multi_source/gtid_ignore_duplicates.result index e142ff8b981..88b525e21ff 100644 --- a/mysql-test/suite/multi_source/gtid_ignore_duplicates.result +++ b/mysql-test/suite/multi_source/gtid_ignore_duplicates.result @@ -174,6 +174,105 @@ a 10 11 12 +*** MDEV-33475: --gtid-ignore-duplicate can double-apply event in case of parallel replication retry +connection server_2; +STOP SLAVE "c2b"; +SET default_master_connection = "c2b"; +include/wait_for_slave_to_stop.inc +STOP SLAVE "a2b"; +SET default_master_connection = "a2b"; +include/wait_for_slave_to_stop.inc +connection server_1; +CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +BEGIN; +INSERT INTO t2 VALUES (0, 0); +INSERT INTO t2 VALUES (1, 0); +INSERT INTO t2 VALUES (2, 0); +INSERT INTO t2 VALUES (3, 0); +INSERT INTO t2 VALUES (4, 0); +INSERT INTO t2 VALUES (5, 0); +INSERT INTO t2 VALUES (6, 0); +INSERT INTO t2 VALUES (7, 0); +INSERT INTO t2 VALUES (8, 0); +INSERT INTO t2 VALUES (9, 0); +COMMIT; +BEGIN; +INSERT INTO t2 VALUES (0+10, 100); +UPDATE t2 SET b=0 WHERE a<10; +INSERT INTO t2 VALUES (0+20, 200); +COMMIT; +BEGIN; +INSERT INTO t2 VALUES (1+10, 100); +UPDATE t2 SET b=1 WHERE a<10; +INSERT INTO t2 VALUES (1+20, 200); +COMMIT; +BEGIN; +INSERT INTO t2 VALUES (2+10, 100); +UPDATE t2 SET b=2 WHERE a<10; +INSERT INTO t2 VALUES (2+20, 200); +COMMIT; +BEGIN; +INSERT INTO t2 VALUES (3+10, 100); +UPDATE t2 SET b=3 WHERE a<10; +INSERT INTO t2 VALUES (3+20, 200); +COMMIT; +BEGIN; +INSERT INTO t2 VALUES (4+10, 100); +UPDATE t2 SET b=4 WHERE a<10; +INSERT INTO t2 VALUES (4+20, 200); +COMMIT; +BEGIN; +INSERT INTO t2 VALUES (5+10, 100); +UPDATE t2 SET b=5 WHERE a<10; +INSERT INTO t2 VALUES (5+20, 200); +COMMIT; +BEGIN; +INSERT INTO t2 VALUES (6+10, 100); +UPDATE t2 SET b=6 WHERE a<10; +INSERT INTO t2 VALUES (6+20, 200); +COMMIT; +BEGIN; +INSERT INTO t2 VALUES (7+10, 100); +UPDATE t2 SET b=7 WHERE a<10; +INSERT INTO t2 VALUES (7+20, 200); +COMMIT; +BEGIN; +INSERT INTO t2 VALUES (8+10, 100); +UPDATE t2 SET b=8 WHERE a<10; +INSERT INTO t2 VALUES (8+20, 200); +COMMIT; +BEGIN; +INSERT INTO t2 VALUES (9+10, 100); +UPDATE t2 SET b=9 WHERE a<10; +INSERT INTO t2 VALUES (9+20, 200); +COMMIT; +SELECT COUNT(*), SUM(a), SUM(b) FROM t2; +COUNT(*) SUM(a) SUM(b) +30 435 3090 +include/save_master_gtid.inc +connection server_2; +SET @old_mode= @@GLOBAL.slave_parallel_mode; +SET GLOBAL slave_parallel_mode=aggressive; +SET default_master_connection = "a2b"; +START SLAVE; +include/wait_for_slave_to_start.inc +SET default_master_connection = "c2b"; +START SLAVE; +include/wait_for_slave_to_start.inc +include/sync_with_master_gtid.inc +SELECT COUNT(*), SUM(a), SUM(b) FROM t2; +COUNT(*) SUM(a) SUM(b) +30 435 3090 +connection server_3; +include/sync_with_master_gtid.inc +SELECT COUNT(*), SUM(a), SUM(b) FROM t2; +COUNT(*) SUM(a) SUM(b) +30 435 3090 +connection server_4; +include/sync_with_master_gtid.inc +SELECT COUNT(*), SUM(a), SUM(b) FROM t2; +COUNT(*) SUM(a) SUM(b) +30 435 3090 *** Test also with not using parallel replication. connection server_1; SET default_master_connection = "b2a"; @@ -474,6 +573,7 @@ Warnings: Note 1938 SLAVE 'a2b' stopped Note 1938 SLAVE 'c2b' stopped SET GLOBAL slave_parallel_threads= @old_parallel; +SET GLOBAL slave_parallel_mode= @old_mode; SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates; connection server_3; SET GLOBAL gtid_domain_id=0; @@ -491,22 +591,22 @@ Note 1938 SLAVE 'a2d' stopped SET GLOBAL slave_parallel_threads= @old_parallel; SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates; connection server_1; -DROP TABLE t1; +DROP TABLE t1, t2; ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; include/reset_master_slave.inc disconnect server_1; connection server_2; -DROP TABLE t1; +DROP TABLE t1, t2; ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; include/reset_master_slave.inc disconnect server_2; connection server_3; -DROP TABLE t1; +DROP TABLE t1, t2; ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; include/reset_master_slave.inc disconnect server_3; connection server_4; -DROP TABLE t1; +DROP TABLE t1, t2; ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; include/reset_master_slave.inc disconnect server_4; diff --git a/mysql-test/suite/multi_source/gtid_ignore_duplicates.test b/mysql-test/suite/multi_source/gtid_ignore_duplicates.test index 3d2d151bd0d..cbc06920b41 100644 --- a/mysql-test/suite/multi_source/gtid_ignore_duplicates.test +++ b/mysql-test/suite/multi_source/gtid_ignore_duplicates.test @@ -173,6 +173,65 @@ SET default_master_connection = "a2b"; SELECT * FROM t1 WHERE a >= 10 ORDER BY a; +--echo *** MDEV-33475: --gtid-ignore-duplicate can double-apply event in case of parallel replication retry + +# Create a bunch of transactions that will cause conflicts and retries. +# The bug was that the retry code was not handling the --gtid-ignore-duplicates +# option, so events could be doubly-applied. + +--connection server_2 +STOP SLAVE "c2b"; +SET default_master_connection = "c2b"; +--source include/wait_for_slave_to_stop.inc +STOP SLAVE "a2b"; +SET default_master_connection = "a2b"; +--source include/wait_for_slave_to_stop.inc + +--connection server_1 +CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +BEGIN; +--let $i= 0 +while ($i < 10) { + eval INSERT INTO t2 VALUES ($i, 0); + inc $i; +} +COMMIT; + +--let $i= 0 +while ($i < 10) { + BEGIN; + eval INSERT INTO t2 VALUES ($i+10, 100); + eval UPDATE t2 SET b=$i WHERE a<10; + eval INSERT INTO t2 VALUES ($i+20, 200); + COMMIT; + inc $i; +} + +SELECT COUNT(*), SUM(a), SUM(b) FROM t2; +--source include/save_master_gtid.inc + +--connection server_2 +SET @old_mode= @@GLOBAL.slave_parallel_mode; +SET GLOBAL slave_parallel_mode=aggressive; +SET default_master_connection = "a2b"; +START SLAVE; +--source include/wait_for_slave_to_start.inc +SET default_master_connection = "c2b"; +START SLAVE; +--source include/wait_for_slave_to_start.inc + +--source include/sync_with_master_gtid.inc +SELECT COUNT(*), SUM(a), SUM(b) FROM t2; + +--connection server_3 +--source include/sync_with_master_gtid.inc +SELECT COUNT(*), SUM(a), SUM(b) FROM t2; + +--connection server_4 +--source include/sync_with_master_gtid.inc +SELECT COUNT(*), SUM(a), SUM(b) FROM t2; + + --echo *** Test also with not using parallel replication. --connection server_1 @@ -414,6 +473,7 @@ SET GLOBAL gtid_domain_id=0; --sorted_result STOP ALL SLAVES; SET GLOBAL slave_parallel_threads= @old_parallel; +SET GLOBAL slave_parallel_mode= @old_mode; SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates; --connection server_3 @@ -431,25 +491,25 @@ SET GLOBAL slave_parallel_threads= @old_parallel; SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates; --connection server_1 -DROP TABLE t1; +DROP TABLE t1, t2; ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; --source include/reset_master_slave.inc --disconnect server_1 --connection server_2 -DROP TABLE t1; +DROP TABLE t1, t2; ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; --source include/reset_master_slave.inc --disconnect server_2 --connection server_3 -DROP TABLE t1; +DROP TABLE t1, t2; ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; --source include/reset_master_slave.inc --disconnect server_3 --connection server_4 -DROP TABLE t1; +DROP TABLE t1, t2; ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; --source include/reset_master_slave.inc --disconnect server_4 diff --git a/mysql-test/suite/parts/inc/partition_crash.inc b/mysql-test/suite/parts/inc/partition_crash.inc index c657ba880c9..bd00f6ca0d5 100644 --- a/mysql-test/suite/parts/inc/partition_crash.inc +++ b/mysql-test/suite/parts/inc/partition_crash.inc @@ -11,7 +11,7 @@ SHOW CREATE TABLE t1; --sorted_result SELECT * FROM t1; ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --disable_reconnect # CR_SERVER_LOST --error 2013 @@ -22,7 +22,7 @@ SELECT * FROM t1; --replace_regex /sql-exchange.*\./sql-exchange./ /sql-shadow-[0-9a-f]*-/sql-shadow-/ --cat_file $DATADIR.files.txt --remove_file $DATADIR.files.txt ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --enable_reconnect --source include/wait_until_connected_again.inc --echo # State after crash recovery diff --git a/mysql-test/suite/parts/r/mdev_21007.result b/mysql-test/suite/parts/r/mdev_21007.result new file mode 100644 index 00000000000..fb2417ac3ae --- /dev/null +++ b/mysql-test/suite/parts/r/mdev_21007.result @@ -0,0 +1,5 @@ +CREATE TABLE t1 (a INT) PARTITION BY RANGE (a) (PARTITION p0 VALUES LESS THAN (1), PARTITION p1 VALUES LESS THAN (MAXVALUE)); +INSERT INTO t1 VALUES (1),(2); +ALTER TABLE t1 MODIFY a INT AUTO_INCREMENT PRIMARY KEY; +UPDATE t1 PARTITION (p1) SET a=9 ORDER BY a LIMIT 1; +DROP TABLE t1; diff --git a/mysql-test/suite/parts/t/mdev_21007.test b/mysql-test/suite/parts/t/mdev_21007.test new file mode 100644 index 00000000000..ec6fbe4d108 --- /dev/null +++ b/mysql-test/suite/parts/t/mdev_21007.test @@ -0,0 +1,9 @@ +--source include/have_partition.inc + +CREATE TABLE t1 (a INT) PARTITION BY RANGE (a) (PARTITION p0 VALUES LESS THAN (1), PARTITION p1 VALUES LESS THAN (MAXVALUE)); +INSERT INTO t1 VALUES (1),(2); +ALTER TABLE t1 MODIFY a INT AUTO_INCREMENT PRIMARY KEY; +UPDATE t1 PARTITION (p1) SET a=9 ORDER BY a LIMIT 1; + +# Cleanup +DROP TABLE t1; diff --git a/mysql-test/suite/perfschema/include/memory_aggregate_load.inc b/mysql-test/suite/perfschema/include/memory_aggregate_load.inc index 7a54d25216e..c6e58d094d6 100644 --- a/mysql-test/suite/perfschema/include/memory_aggregate_load.inc +++ b/mysql-test/suite/perfschema/include/memory_aggregate_load.inc @@ -274,7 +274,6 @@ execute dump_users; execute dump_hosts; --disconnect con1 ---disconnect con5 --connection default @@ -283,6 +282,8 @@ let $wait_condition= select count(*) = 0 from performance_schema.threads where `TYPE`='FOREGROUND' and PROCESSLIST_USER= 'user1'; --source include/wait_condition.inc + +--disconnect con5 let $wait_condition= select count(*) = 1 from performance_schema.threads where `TYPE`='FOREGROUND' and PROCESSLIST_USER= 'user4'; diff --git a/mysql-test/suite/perfschema/include/program_execution.inc b/mysql-test/suite/perfschema/include/program_execution.inc index 8c0bc691898..f774a4d7b50 100644 --- a/mysql-test/suite/perfschema/include/program_execution.inc +++ b/mysql-test/suite/perfschema/include/program_execution.inc @@ -32,7 +32,7 @@ SET GLOBAL event_scheduler=ON; CREATE TABLE table_t(a INT); DELIMITER |; -CREATE EVENT e1 ON SCHEDULE EVERY 2 SECOND DO +CREATE EVENT e1 ON SCHEDULE EVERY 2 SECOND ON COMPLETION NOT PRESERVE DO BEGIN INSERT INTO table_t VALUES(1); END| diff --git a/mysql-test/suite/perfschema/r/max_program_zero.result b/mysql-test/suite/perfschema/r/max_program_zero.result index 5435efb34ae..6078fb8ddc9 100644 --- a/mysql-test/suite/perfschema/r/max_program_zero.result +++ b/mysql-test/suite/perfschema/r/max_program_zero.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/memory_aggregate.result b/mysql-test/suite/perfschema/r/memory_aggregate.result index 69eb033e74b..1d963dd8caa 100644 --- a/mysql-test/suite/perfschema/r/memory_aggregate.result +++ b/mysql-test/suite/perfschema/r/memory_aggregate.result @@ -2507,8 +2507,8 @@ execute dump_hosts; HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS localhost 6 6 disconnect con1; -disconnect con5; connection default; +disconnect con5; "================== con1/con5 disconnected ==================" "================== Step 10 ==================" call dump_thread(); diff --git a/mysql-test/suite/perfschema/r/memory_aggregate_32bit.result b/mysql-test/suite/perfschema/r/memory_aggregate_32bit.result index 2b8ee675650..387af11f91a 100644 --- a/mysql-test/suite/perfschema/r/memory_aggregate_32bit.result +++ b/mysql-test/suite/perfschema/r/memory_aggregate_32bit.result @@ -2507,8 +2507,8 @@ execute dump_hosts; HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS localhost 6 6 disconnect con1; -disconnect con5; connection default; +disconnect con5; "================== con1/con5 disconnected ==================" "================== Step 10 ==================" call dump_thread(); diff --git a/mysql-test/suite/perfschema/r/memory_aggregate_no_a.result b/mysql-test/suite/perfschema/r/memory_aggregate_no_a.result index b5c8e1cd3c7..abac503b965 100644 --- a/mysql-test/suite/perfschema/r/memory_aggregate_no_a.result +++ b/mysql-test/suite/perfschema/r/memory_aggregate_no_a.result @@ -1903,8 +1903,8 @@ execute dump_hosts; HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS localhost 6 6 disconnect con1; -disconnect con5; connection default; +disconnect con5; "================== con1/con5 disconnected ==================" "================== Step 10 ==================" call dump_thread(); diff --git a/mysql-test/suite/perfschema/r/memory_aggregate_no_a_no_h.result b/mysql-test/suite/perfschema/r/memory_aggregate_no_a_no_h.result index cc0e0c03dcf..f63e6f1d002 100644 --- a/mysql-test/suite/perfschema/r/memory_aggregate_no_a_no_h.result +++ b/mysql-test/suite/perfschema/r/memory_aggregate_no_a_no_h.result @@ -1653,8 +1653,8 @@ user4 2 2 execute dump_hosts; HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS disconnect con1; -disconnect con5; connection default; +disconnect con5; "================== con1/con5 disconnected ==================" "================== Step 10 ==================" call dump_thread(); diff --git a/mysql-test/suite/perfschema/r/memory_aggregate_no_a_no_u.result b/mysql-test/suite/perfschema/r/memory_aggregate_no_a_no_u.result index 8b24b5b565b..32785952fe7 100644 --- a/mysql-test/suite/perfschema/r/memory_aggregate_no_a_no_u.result +++ b/mysql-test/suite/perfschema/r/memory_aggregate_no_a_no_u.result @@ -1343,8 +1343,8 @@ execute dump_hosts; HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS localhost 6 6 disconnect con1; -disconnect con5; connection default; +disconnect con5; "================== con1/con5 disconnected ==================" "================== Step 10 ==================" call dump_thread(); diff --git a/mysql-test/suite/perfschema/r/memory_aggregate_no_a_no_u_no_h.result b/mysql-test/suite/perfschema/r/memory_aggregate_no_a_no_u_no_h.result index 45cbaf88372..e68f0e1baf6 100644 --- a/mysql-test/suite/perfschema/r/memory_aggregate_no_a_no_u_no_h.result +++ b/mysql-test/suite/perfschema/r/memory_aggregate_no_a_no_u_no_h.result @@ -1093,8 +1093,8 @@ USER CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_hosts; HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS disconnect con1; -disconnect con5; connection default; +disconnect con5; "================== con1/con5 disconnected ==================" "================== Step 10 ==================" call dump_thread(); diff --git a/mysql-test/suite/perfschema/r/memory_aggregate_no_h.result b/mysql-test/suite/perfschema/r/memory_aggregate_no_h.result index 35d528bf63c..e3b7cd0f998 100644 --- a/mysql-test/suite/perfschema/r/memory_aggregate_no_h.result +++ b/mysql-test/suite/perfschema/r/memory_aggregate_no_h.result @@ -2257,8 +2257,8 @@ user4 2 2 execute dump_hosts; HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS disconnect con1; -disconnect con5; connection default; +disconnect con5; "================== con1/con5 disconnected ==================" "================== Step 10 ==================" call dump_thread(); diff --git a/mysql-test/suite/perfschema/r/memory_aggregate_no_u.result b/mysql-test/suite/perfschema/r/memory_aggregate_no_u.result index 1f800ce4ba6..fd9f2c69a42 100644 --- a/mysql-test/suite/perfschema/r/memory_aggregate_no_u.result +++ b/mysql-test/suite/perfschema/r/memory_aggregate_no_u.result @@ -1947,8 +1947,8 @@ execute dump_hosts; HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS localhost 6 6 disconnect con1; -disconnect con5; connection default; +disconnect con5; "================== con1/con5 disconnected ==================" "================== Step 10 ==================" call dump_thread(); diff --git a/mysql-test/suite/perfschema/r/memory_aggregate_no_u_no_h.result b/mysql-test/suite/perfschema/r/memory_aggregate_no_u_no_h.result index b1ac5f24ec9..fdbd2d75d56 100644 --- a/mysql-test/suite/perfschema/r/memory_aggregate_no_u_no_h.result +++ b/mysql-test/suite/perfschema/r/memory_aggregate_no_u_no_h.result @@ -1697,8 +1697,8 @@ USER CURRENT_CONNECTIONS TOTAL_CONNECTIONS execute dump_hosts; HOST CURRENT_CONNECTIONS TOTAL_CONNECTIONS disconnect con1; -disconnect con5; connection default; +disconnect con5; "================== con1/con5 disconnected ==================" "================== Step 10 ==================" call dump_thread(); diff --git a/mysql-test/suite/perfschema/r/misc.result b/mysql-test/suite/perfschema/r/misc.result index 2258cbceea4..6bc0fa32314 100644 --- a/mysql-test/suite/perfschema/r/misc.result +++ b/mysql-test/suite/perfschema/r/misc.result @@ -94,7 +94,7 @@ test t_60905 NULL 5 5 0 1 DROP TABLE t_60905; show global variables like "performance_schema_max_thread_instances"; Variable_name Value -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 explain select * from performance_schema.threads; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE threads ALL NULL NULL NULL NULL 256 diff --git a/mysql-test/suite/perfschema/r/ortho_iter.result b/mysql-test/suite/perfschema/r/ortho_iter.result index 9489c1049e5..2dacee0ac27 100644 --- a/mysql-test/suite/perfschema/r/ortho_iter.result +++ b/mysql-test/suite/perfschema/r/ortho_iter.result @@ -261,7 +261,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/privilege_table_io.result b/mysql-test/suite/perfschema/r/privilege_table_io.result index 8be4b9583ec..35a905895b1 100644 --- a/mysql-test/suite/perfschema/r/privilege_table_io.result +++ b/mysql-test/suite/perfschema/r/privilege_table_io.result @@ -63,7 +63,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_disable_idle.result b/mysql-test/suite/perfschema/r/start_server_disable_idle.result index bfc49fd3480..536d2f24e0d 100644 --- a/mysql-test/suite/perfschema/r/start_server_disable_idle.result +++ b/mysql-test/suite/perfschema/r/start_server_disable_idle.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_disable_stages.result b/mysql-test/suite/perfschema/r/start_server_disable_stages.result index e9f20398467..c2682733206 100644 --- a/mysql-test/suite/perfschema/r/start_server_disable_stages.result +++ b/mysql-test/suite/perfschema/r/start_server_disable_stages.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_disable_statements.result b/mysql-test/suite/perfschema/r/start_server_disable_statements.result index ffb45f4f55f..1d150f42fdd 100644 --- a/mysql-test/suite/perfschema/r/start_server_disable_statements.result +++ b/mysql-test/suite/perfschema/r/start_server_disable_statements.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_disable_transactions.result b/mysql-test/suite/perfschema/r/start_server_disable_transactions.result index e271d5a10e6..0494070cb5d 100644 --- a/mysql-test/suite/perfschema/r/start_server_disable_transactions.result +++ b/mysql-test/suite/perfschema/r/start_server_disable_transactions.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_disable_waits.result b/mysql-test/suite/perfschema/r/start_server_disable_waits.result index 833da22583e..fa53fff00b3 100644 --- a/mysql-test/suite/perfschema/r/start_server_disable_waits.result +++ b/mysql-test/suite/perfschema/r/start_server_disable_waits.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_innodb.result b/mysql-test/suite/perfschema/r/start_server_innodb.result index e3ff0f514a7..968309c704b 100644 --- a/mysql-test/suite/perfschema/r/start_server_innodb.result +++ b/mysql-test/suite/perfschema/r/start_server_innodb.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_low_index.result b/mysql-test/suite/perfschema/r/start_server_low_index.result index ffdf9d65b87..78d976b8a5e 100644 --- a/mysql-test/suite/perfschema/r/start_server_low_index.result +++ b/mysql-test/suite/perfschema/r/start_server_low_index.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_low_table_lock.result b/mysql-test/suite/perfschema/r/start_server_low_table_lock.result index dbb404f6129..ceb052c97d5 100644 --- a/mysql-test/suite/perfschema/r/start_server_low_table_lock.result +++ b/mysql-test/suite/perfschema/r/start_server_low_table_lock.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 1 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_account.result b/mysql-test/suite/perfschema/r/start_server_no_account.result index f92b0e6bec6..6582b67f10a 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_account.result +++ b/mysql-test/suite/perfschema/r/start_server_no_account.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_cond_class.result b/mysql-test/suite/perfschema/r/start_server_no_cond_class.result index fefad55c209..7f698404a5c 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_cond_class.result +++ b/mysql-test/suite/perfschema/r/start_server_no_cond_class.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_cond_inst.result b/mysql-test/suite/perfschema/r/start_server_no_cond_inst.result index 0c2f65f6ac9..d2a84d67951 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_cond_inst.result +++ b/mysql-test/suite/perfschema/r/start_server_no_cond_inst.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_file_class.result b/mysql-test/suite/perfschema/r/start_server_no_file_class.result index c3f06b53425..1d4183cc670 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_file_class.result +++ b/mysql-test/suite/perfschema/r/start_server_no_file_class.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_file_inst.result b/mysql-test/suite/perfschema/r/start_server_no_file_inst.result index fd39807d567..91e326c1013 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_file_inst.result +++ b/mysql-test/suite/perfschema/r/start_server_no_file_inst.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_host.result b/mysql-test/suite/perfschema/r/start_server_no_host.result index 43111c5ec40..d27b3846551 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_host.result +++ b/mysql-test/suite/perfschema/r/start_server_no_host.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_index.result b/mysql-test/suite/perfschema/r/start_server_no_index.result index 15d1184bcbe..e8705014117 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_index.result +++ b/mysql-test/suite/perfschema/r/start_server_no_index.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_mdl.result b/mysql-test/suite/perfschema/r/start_server_no_mdl.result index b8de90453ce..3665a88e0ac 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_mdl.result +++ b/mysql-test/suite/perfschema/r/start_server_no_mdl.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_memory_class.result b/mysql-test/suite/perfschema/r/start_server_no_memory_class.result index 60066264c90..3155cae5c78 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_memory_class.result +++ b/mysql-test/suite/perfschema/r/start_server_no_memory_class.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_mutex_class.result b/mysql-test/suite/perfschema/r/start_server_no_mutex_class.result index 3353b46bbcb..6e302fa3bae 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_mutex_class.result +++ b/mysql-test/suite/perfschema/r/start_server_no_mutex_class.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_mutex_inst.result b/mysql-test/suite/perfschema/r/start_server_no_mutex_inst.result index d41da361733..2ece8debdc0 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_mutex_inst.result +++ b/mysql-test/suite/perfschema/r/start_server_no_mutex_inst.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_prepared_stmts_instances.result b/mysql-test/suite/perfschema/r/start_server_no_prepared_stmts_instances.result index 4919de6bb6c..63ef23d8b2e 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_prepared_stmts_instances.result +++ b/mysql-test/suite/perfschema/r/start_server_no_prepared_stmts_instances.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_rwlock_class.result b/mysql-test/suite/perfschema/r/start_server_no_rwlock_class.result index 02a119bdc68..a62821a6dd5 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_rwlock_class.result +++ b/mysql-test/suite/perfschema/r/start_server_no_rwlock_class.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_rwlock_inst.result b/mysql-test/suite/perfschema/r/start_server_no_rwlock_inst.result index ead01ce2d0e..b0bbe2d08b4 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_rwlock_inst.result +++ b/mysql-test/suite/perfschema/r/start_server_no_rwlock_inst.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_setup_actors.result b/mysql-test/suite/perfschema/r/start_server_no_setup_actors.result index a99f1c0f9be..902fd701b30 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_setup_actors.result +++ b/mysql-test/suite/perfschema/r/start_server_no_setup_actors.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 0 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_setup_objects.result b/mysql-test/suite/perfschema/r/start_server_no_setup_objects.result index 7c148889412..6a35811711f 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_setup_objects.result +++ b/mysql-test/suite/perfschema/r/start_server_no_setup_objects.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 0 diff --git a/mysql-test/suite/perfschema/r/start_server_no_socket_class.result b/mysql-test/suite/perfschema/r/start_server_no_socket_class.result index dec0680c511..613bd76840a 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_socket_class.result +++ b/mysql-test/suite/perfschema/r/start_server_no_socket_class.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_socket_inst.result b/mysql-test/suite/perfschema/r/start_server_no_socket_inst.result index 20adf1a9f64..d569c678420 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_socket_inst.result +++ b/mysql-test/suite/perfschema/r/start_server_no_socket_inst.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_stage_class.result b/mysql-test/suite/perfschema/r/start_server_no_stage_class.result index 044f9475041..26bb66c8556 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_stage_class.result +++ b/mysql-test/suite/perfschema/r/start_server_no_stage_class.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_stages_history.result b/mysql-test/suite/perfschema/r/start_server_no_stages_history.result index 350f2c6637d..25fbcbeb422 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_stages_history.result +++ b/mysql-test/suite/perfschema/r/start_server_no_stages_history.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_stages_history_long.result b/mysql-test/suite/perfschema/r/start_server_no_stages_history_long.result index d2d7063c32f..98347eb76e5 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_stages_history_long.result +++ b/mysql-test/suite/perfschema/r/start_server_no_stages_history_long.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_statement_class.result b/mysql-test/suite/perfschema/r/start_server_no_statement_class.result index ca7c49cd51a..88f9efe2f79 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_statement_class.result +++ b/mysql-test/suite/perfschema/r/start_server_no_statement_class.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_statements_history.result b/mysql-test/suite/perfschema/r/start_server_no_statements_history.result index 8bcb3c56a00..924cfd705a2 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_statements_history.result +++ b/mysql-test/suite/perfschema/r/start_server_no_statements_history.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_statements_history_long.result b/mysql-test/suite/perfschema/r/start_server_no_statements_history_long.result index 2a2bf5d3f7c..d60518b683e 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_statements_history_long.result +++ b/mysql-test/suite/perfschema/r/start_server_no_statements_history_long.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_table_hdl.result b/mysql-test/suite/perfschema/r/start_server_no_table_hdl.result index ec6e40acc00..fa4e3697108 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_table_hdl.result +++ b/mysql-test/suite/perfschema/r/start_server_no_table_hdl.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 0 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_table_inst.result b/mysql-test/suite/perfschema/r/start_server_no_table_inst.result index b3f1e4cbcf2..07f6f1ed843 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_table_inst.result +++ b/mysql-test/suite/perfschema/r/start_server_no_table_inst.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 0 performance_schema_max_table_lock_stat 0 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_table_lock.result b/mysql-test/suite/perfschema/r/start_server_no_table_lock.result index baf9f761358..e0649aa311c 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_table_lock.result +++ b/mysql-test/suite/perfschema/r/start_server_no_table_lock.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 0 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_thread_class.result b/mysql-test/suite/perfschema/r/start_server_no_thread_class.result index cd204f3d811..3eec2ef9465 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_thread_class.result +++ b/mysql-test/suite/perfschema/r/start_server_no_thread_class.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 0 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_transactions_history.result b/mysql-test/suite/perfschema/r/start_server_no_transactions_history.result index f5a12e5473d..65017955831 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_transactions_history.result +++ b/mysql-test/suite/perfschema/r/start_server_no_transactions_history.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_transactions_history_long.result b/mysql-test/suite/perfschema/r/start_server_no_transactions_history_long.result index 76ae9d5fa4e..586a61ba8e0 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_transactions_history_long.result +++ b/mysql-test/suite/perfschema/r/start_server_no_transactions_history_long.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_user.result b/mysql-test/suite/perfschema/r/start_server_no_user.result index 4bd472a22a9..234dbbb8f60 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_user.result +++ b/mysql-test/suite/perfschema/r/start_server_no_user.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_waits_history.result b/mysql-test/suite/perfschema/r/start_server_no_waits_history.result index f59b156ce1e..b01fa65ffec 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_waits_history.result +++ b/mysql-test/suite/perfschema/r/start_server_no_waits_history.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_no_waits_history_long.result b/mysql-test/suite/perfschema/r/start_server_no_waits_history_long.result index cc70572c7ef..f4a572856a4 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_waits_history_long.result +++ b/mysql-test/suite/perfschema/r/start_server_no_waits_history_long.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_off.result b/mysql-test/suite/perfschema/r/start_server_off.result index a53d591938c..bb7ff817d75 100644 --- a/mysql-test/suite/perfschema/r/start_server_off.result +++ b/mysql-test/suite/perfschema/r/start_server_off.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_on.result b/mysql-test/suite/perfschema/r/start_server_on.result index e3ff0f514a7..968309c704b 100644 --- a/mysql-test/suite/perfschema/r/start_server_on.result +++ b/mysql-test/suite/perfschema/r/start_server_on.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/start_server_variables.result b/mysql-test/suite/perfschema/r/start_server_variables.result index 7d1d1e05375..d7cb8fdb973 100644 --- a/mysql-test/suite/perfschema/r/start_server_variables.result +++ b/mysql-test/suite/perfschema/r/start_server_variables.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 @@ -188,7 +188,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/statement_program_lost_inst.result b/mysql-test/suite/perfschema/r/statement_program_lost_inst.result index 05ec7b0b2b5..97fb689fd33 100644 --- a/mysql-test/suite/perfschema/r/statement_program_lost_inst.result +++ b/mysql-test/suite/perfschema/r/statement_program_lost_inst.result @@ -141,7 +141,7 @@ performance_schema_max_table_handles 1000 performance_schema_max_table_instances 500 performance_schema_max_table_lock_stat 500 performance_schema_max_thread_classes 50 -performance_schema_max_thread_instances 200 +performance_schema_max_thread_instances 400 performance_schema_session_connect_attrs_size 2048 performance_schema_setup_actors_size 100 performance_schema_setup_objects_size 100 diff --git a/mysql-test/suite/perfschema/r/statement_program_nesting_event_check.result b/mysql-test/suite/perfschema/r/statement_program_nesting_event_check.result index 5e376a12a18..1a973c9448b 100644 --- a/mysql-test/suite/perfschema/r/statement_program_nesting_event_check.result +++ b/mysql-test/suite/perfschema/r/statement_program_nesting_event_check.result @@ -145,7 +145,7 @@ Bollywood # Event SET GLOBAL event_scheduler=ON; CREATE TABLE table_t(a INT); -CREATE EVENT e1 ON SCHEDULE EVERY 2 SECOND DO +CREATE EVENT e1 ON SCHEDULE EVERY 2 SECOND ON COMPLETION NOT PRESERVE DO BEGIN INSERT INTO table_t VALUES(1); END| @@ -165,7 +165,7 @@ statement/sql/call_procedure CALL SampleProc1(30,40,50) NULL NULL 0 statement/sql/call_procedure CALL SampleProc2("Jwalamukhi",34) NULL NULL 0 statement/sql/call_procedure CALL SampleProc3() NULL NULL 0 statement/sql/call_procedure CALL SampleProc4() NULL NULL 0 -statement/sql/create_event CREATE EVENT e1 ON SCHEDULE EVERY 2 SECOND DO +statement/sql/create_event CREATE EVENT e1 ON SCHEDULE EVERY 2 SECOND ON COMPLETION NOT PRESERVE DO BEGIN INSERT INTO table_t VALUES(1); END NULL NULL 0 diff --git a/mysql-test/suite/perfschema/r/statement_program_non_nested.result b/mysql-test/suite/perfschema/r/statement_program_non_nested.result index af9807cbc97..1c75dac11ac 100644 --- a/mysql-test/suite/perfschema/r/statement_program_non_nested.result +++ b/mysql-test/suite/perfschema/r/statement_program_non_nested.result @@ -145,7 +145,7 @@ Bollywood # Event SET GLOBAL event_scheduler=ON; CREATE TABLE table_t(a INT); -CREATE EVENT e1 ON SCHEDULE EVERY 2 SECOND DO +CREATE EVENT e1 ON SCHEDULE EVERY 2 SECOND ON COMPLETION NOT PRESERVE DO BEGIN INSERT INTO table_t VALUES(1); END| @@ -182,7 +182,7 @@ statement/sql/call_procedure CALL SampleProc1(30,40,50) stored_programs NULL NUL statement/sql/call_procedure CALL SampleProc2("Jwalamukhi",34) stored_programs NULL NULL NULL NULL 0 statement/sql/call_procedure CALL SampleProc3() stored_programs NULL NULL NULL NULL 0 statement/sql/call_procedure CALL SampleProc4() stored_programs NULL NULL NULL NULL 0 -statement/sql/create_event CREATE EVENT e1 ON SCHEDULE EVERY 2 SECOND DO +statement/sql/create_event CREATE EVENT e1 ON SCHEDULE EVERY 2 SECOND ON COMPLETION NOT PRESERVE DO BEGIN INSERT INTO table_t VALUES(1); END stored_programs NULL NULL NULL NULL 0 @@ -553,7 +553,7 @@ Bollywood # Event SET GLOBAL event_scheduler=ON; CREATE TABLE table_t(a INT); -CREATE EVENT e1 ON SCHEDULE EVERY 2 SECOND DO +CREATE EVENT e1 ON SCHEDULE EVERY 2 SECOND ON COMPLETION NOT PRESERVE DO BEGIN INSERT INTO table_t VALUES(1); END| diff --git a/mysql-test/suite/perfschema/r/threads_history.result b/mysql-test/suite/perfschema/r/threads_history.result index 364a5f6f9e3..d72ace62255 100644 --- a/mysql-test/suite/perfschema/r/threads_history.result +++ b/mysql-test/suite/perfschema/r/threads_history.result @@ -24,27 +24,22 @@ events_waits_history_long YES global_instrumentation YES thread_instrumentation YES statements_digest YES -# Switch to (con1, localhost, user1, , ) connect con1, localhost, user1, , ; update performance_schema.threads set INSTRUMENTED='YES', HISTORY='YES' where PROCESSLIST_ID = connection_id(); -# Switch to (con2, localhost, user2, , ) connect con2, localhost, user2, , ; update performance_schema.threads set INSTRUMENTED='YES', HISTORY='NO' where PROCESSLIST_ID = connection_id(); -# Switch to (con3, localhost, user3, , ) connect con3, localhost, user3, , ; update performance_schema.threads set INSTRUMENTED='NO', HISTORY='YES' where PROCESSLIST_ID = connection_id(); -# Switch to (con4, localhost, user4, , ) connect con4, localhost, user4, , ; update performance_schema.threads set INSTRUMENTED='NO', HISTORY='NO' where PROCESSLIST_ID = connection_id(); -# Switch to connection default connection default; truncate table performance_schema.events_transactions_current; truncate table performance_schema.events_transactions_history; @@ -58,7 +53,6 @@ truncate table performance_schema.events_stages_history_long; truncate table performance_schema.events_waits_current; truncate table performance_schema.events_waits_history; truncate table performance_schema.events_waits_history_long; -# Switch to connection con1 connection con1; XA START 'XA_CON1', 'XA_BQUAL', 12; select "Hi from con1"; @@ -67,7 +61,6 @@ Hi from con1 XA END 'XA_CON1', 'XA_BQUAL', 12; XA PREPARE 'XA_CON1', 'XA_BQUAL', 12; XA COMMIT 'XA_CON1', 'XA_BQUAL', 12; -# Switch to connection con2 connection con2; XA START 'XA_CON2', 'XA_BQUAL', 12; select "Hi from con2"; @@ -76,7 +69,6 @@ Hi from con2 XA END 'XA_CON2', 'XA_BQUAL', 12; XA PREPARE 'XA_CON2', 'XA_BQUAL', 12; XA COMMIT 'XA_CON2', 'XA_BQUAL', 12; -# Switch to connection con3 connection con3; XA START 'XA_CON3', 'XA_BQUAL', 12; select "Hi from con3"; @@ -85,7 +77,6 @@ Hi from con3 XA END 'XA_CON3', 'XA_BQUAL', 12; XA PREPARE 'XA_CON3', 'XA_BQUAL', 12; XA COMMIT 'XA_CON3', 'XA_BQUAL', 12; -# Switch to connection con4 connection con4; XA START 'XA_CON4', 'XA_BQUAL', 12; select "Hi from con4"; @@ -95,72 +86,124 @@ XA END 'XA_CON4', 'XA_BQUAL', 12; XA PREPARE 'XA_CON4', 'XA_BQUAL', 12; XA COMMIT 'XA_CON4', 'XA_BQUAL', 12; connection default; -"=========================== Transactions user 1" +########################### Transactions user 1 - 1 +select /*1-1*/ XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_current +where THREAD_ID = $con1_thread_id; XID_FORMAT_ID XID_GTRID XID_BQUAL 12 XA_CON1 XA_BQUAL +select /*1-1*/ XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_history +where THREAD_ID = $con1_thread_id; XID_FORMAT_ID XID_GTRID XID_BQUAL 12 XA_CON1 XA_BQUAL +select /*1-1*/ XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_history_long +where THREAD_ID = $con1_thread_id; XID_FORMAT_ID XID_GTRID XID_BQUAL 12 XA_CON1 XA_BQUAL -"=========================== Transactions user 2" +########################### Transactions user 2 - 1 +select /*2-1*/ XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_current +where THREAD_ID = $con2_thread_id; XID_FORMAT_ID XID_GTRID XID_BQUAL 12 XA_CON2 XA_BQUAL +select /*2-1*/ count(*) from performance_schema.events_transactions_history +where THREAD_ID = $con2_thread_id; count(*) 0 +select /*2-1*/ count(*) from performance_schema.events_transactions_history_long +where THREAD_ID = $con2_thread_id; count(*) 0 -"=========================== Transactions user 3" +########################### Transactions user 3 - 1 +select /*3-1*/ count(*) from performance_schema.events_transactions_current +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-1*/ count(*) from performance_schema.events_transactions_history +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-1*/ count(*) from performance_schema.events_transactions_history_long +where THREAD_ID = $con3_thread_id; count(*) 0 -"=========================== Transactions user 4" +########################### Transactions user 4 - 1 +select /*4-1*/ count(*) from performance_schema.events_transactions_current +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-1*/ count(*) from performance_schema.events_transactions_history +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-1*/ count(*) from performance_schema.events_transactions_history_long +where THREAD_ID = $con4_thread_id; count(*) 0 -"=========================== Statements user 1" +########################### Statements user 1 - 1 +select /*1-1*/ EVENT_NAME, SQL_TEXT from performance_schema.events_statements_current +where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME SQL_TEXT statement/sql/xa_commit XA COMMIT 'XA_CON1', 'XA_BQUAL', 12 +select /*1-1*/ EVENT_NAME, SQL_TEXT from performance_schema.events_statements_history +where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME SQL_TEXT statement/sql/xa_start XA START 'XA_CON1', 'XA_BQUAL', 12 statement/sql/select select "Hi from con1" statement/sql/xa_end XA END 'XA_CON1', 'XA_BQUAL', 12 statement/sql/xa_prepare XA PREPARE 'XA_CON1', 'XA_BQUAL', 12 statement/sql/xa_commit XA COMMIT 'XA_CON1', 'XA_BQUAL', 12 +select /*1-1*/ EVENT_NAME, SQL_TEXT from performance_schema.events_statements_history_long +where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME SQL_TEXT statement/sql/xa_start XA START 'XA_CON1', 'XA_BQUAL', 12 statement/sql/select select "Hi from con1" statement/sql/xa_end XA END 'XA_CON1', 'XA_BQUAL', 12 statement/sql/xa_prepare XA PREPARE 'XA_CON1', 'XA_BQUAL', 12 statement/sql/xa_commit XA COMMIT 'XA_CON1', 'XA_BQUAL', 12 -"=========================== Statements user 2" +########################### Statements user 2 - 1 +select /*2-1*/ EVENT_NAME, SQL_TEXT from performance_schema.events_statements_current +where THREAD_ID = $con2_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME SQL_TEXT statement/sql/xa_commit XA COMMIT 'XA_CON2', 'XA_BQUAL', 12 +select /*2-1*/ count(*) from performance_schema.events_statements_history +where THREAD_ID = $con2_thread_id; count(*) 0 +select /*2-1*/ count(*) from performance_schema.events_statements_history_long +where THREAD_ID = $con2_thread_id; count(*) 0 -"=========================== Statements user 3" +########################### Statements user 3 - 1 +select /*3-1*/ count(*) from performance_schema.events_statements_current +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-1*/ count(*) from performance_schema.events_statements_history +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-1*/ count(*) from performance_schema.events_statements_history_long +where THREAD_ID = $con3_thread_id; count(*) 0 -"=========================== Statements user 4" +########################### Statements user 4 - 1 +select /*4-1*/ count(*) from performance_schema.events_statements_current +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-1*/ count(*) from performance_schema.events_statements_history +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-1*/ count(*) from performance_schema.events_statements_history_long +where THREAD_ID = $con4_thread_id; count(*) 0 -"=========================== Stages user 1" +########################### Stages user 1 - 1 +select /*1-1*/ EVENT_NAME from performance_schema.events_stages_current +where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME +select /*1-1*/ EVENT_NAME from performance_schema.events_stages_history +where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME stage/sql/Starting cleanup stage/sql/Freeing items @@ -172,6 +215,8 @@ stage/sql/Query end stage/sql/Starting cleanup stage/sql/Freeing items stage/sql/Reset for next command +select /*1-1*/ EVENT_NAME from performance_schema.events_stages_history_long +where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME stage/sql/starting stage/sql/Query end @@ -215,55 +260,96 @@ stage/sql/Query end stage/sql/Starting cleanup stage/sql/Freeing items stage/sql/Reset for next command -"=========================== Stages user 2" +########################### Stages user 2 - 1 +select /*2-1*/ EVENT_NAME from performance_schema.events_stages_current +where THREAD_ID = $con2_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME +select /*2-1*/ count(*) from performance_schema.events_stages_history +where THREAD_ID = $con2_thread_id; count(*) 0 +select /*2-1*/ count(*) from performance_schema.events_stages_history_long +where THREAD_ID = $con2_thread_id; count(*) 0 -"=========================== Stages user 3" +########################### Stages user 3 - 1 +select /*3-1*/ count(*) from performance_schema.events_stages_current +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-1*/ count(*) from performance_schema.events_stages_history +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-1*/ count(*) from performance_schema.events_stages_history_long +where THREAD_ID = $con3_thread_id; count(*) 0 -"=========================== Stages user 4" +########################### Stages user 4 - 1 +select /*4-1*/ count(*) from performance_schema.events_stages_current +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-1*/ count(*) from performance_schema.events_stages_history +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-1*/ count(*) from performance_schema.events_stages_history_long +where THREAD_ID = $con4_thread_id; count(*) 0 -"=========================== Waits user 1" +########################### Waits user 1 - 1 +select /*1-1*/ EVENT_NAME from performance_schema.events_waits_current +where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME idle +select /*1-1*/ (count(*) > 5) as has_waits from performance_schema.events_waits_history +where THREAD_ID = $con1_thread_id; has_waits 1 +select /*1-1*/ (count(*) > 15) as has_waits from performance_schema.events_waits_history_long +where THREAD_ID = $con1_thread_id; has_waits 1 -"=========================== Waits user 2" +########################### Waits user 2 - 1 +select /*2-1*/ EVENT_NAME from performance_schema.events_waits_current +where THREAD_ID = $con2_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME idle +select /*2-1*/ count(*) from performance_schema.events_waits_history +where THREAD_ID = $con2_thread_id; count(*) 0 +select /*2-1*/ count(*) from performance_schema.events_waits_history_long +where THREAD_ID = $con2_thread_id; count(*) 0 -"=========================== Waits user 3" +########################### Waits user 3 - 1 +select /*3-1*/ count(*) from performance_schema.events_waits_current +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-1*/ count(*) from performance_schema.events_waits_history +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-1*/ count(*) from performance_schema.events_waits_history_long +where THREAD_ID = $con3_thread_id; count(*) 0 -"=========================== Waits user 4" +########################### Waits user 4 - 1 +select /*4-1*/ count(*) from performance_schema.events_waits_current +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-1*/ count(*) from performance_schema.events_waits_history +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-1*/ count(*) from performance_schema.events_waits_history_long +where THREAD_ID = $con4_thread_id; count(*) 0 -# Switch to connection default, disable consumers connection default; update performance_schema.setup_consumers set enabled='NO' where name like "%history%"; @@ -296,7 +382,6 @@ truncate table performance_schema.events_stages_history_long; truncate table performance_schema.events_waits_current; truncate table performance_schema.events_waits_history; truncate table performance_schema.events_waits_history_long; -# Switch to connection con1 connection con1; XA START 'XA_CON1', 'XA_BQUAL', 12; select "Hi from con1"; @@ -305,7 +390,6 @@ Hi from con1 XA END 'XA_CON1', 'XA_BQUAL', 12; XA PREPARE 'XA_CON1', 'XA_BQUAL', 12; XA COMMIT 'XA_CON1', 'XA_BQUAL', 12; -# Switch to connection con2 connection con2; XA START 'XA_CON2', 'XA_BQUAL', 12; select "Hi from con2"; @@ -314,7 +398,6 @@ Hi from con2 XA END 'XA_CON2', 'XA_BQUAL', 12; XA PREPARE 'XA_CON2', 'XA_BQUAL', 12; XA COMMIT 'XA_CON2', 'XA_BQUAL', 12; -# Switch to connection con3 connection con3; XA START 'XA_CON3', 'XA_BQUAL', 12; select "Hi from con3"; @@ -323,7 +406,6 @@ Hi from con3 XA END 'XA_CON3', 'XA_BQUAL', 12; XA PREPARE 'XA_CON3', 'XA_BQUAL', 12; XA COMMIT 'XA_CON3', 'XA_BQUAL', 12; -# Switch to connection con4 connection con4; XA START 'XA_CON4', 'XA_BQUAL', 12; select "Hi from con4"; @@ -333,117 +415,212 @@ XA END 'XA_CON4', 'XA_BQUAL', 12; XA PREPARE 'XA_CON4', 'XA_BQUAL', 12; XA COMMIT 'XA_CON4', 'XA_BQUAL', 12; connection default; -"=========================== Transactions user 1" +########################### Transactions user 1 - 2 +select /*1-2*/ XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_current +where THREAD_ID = $con1_thread_id; XID_FORMAT_ID XID_GTRID XID_BQUAL 12 XA_CON1 XA_BQUAL +select /*1-2*/ count(*) from performance_schema.events_transactions_history +where THREAD_ID = $con1_thread_id; count(*) 0 +select /*1-2*/ count(*) from performance_schema.events_transactions_history_long +where THREAD_ID = $con1_thread_id; count(*) 0 -"=========================== Transactions user 2" +########################### Transactions user 2 - 2 +select /*2-2*/ XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_current +where THREAD_ID = $con2_thread_id; XID_FORMAT_ID XID_GTRID XID_BQUAL 12 XA_CON2 XA_BQUAL +select /*2-2*/ count(*) from performance_schema.events_transactions_history +where THREAD_ID = $con2_thread_id; count(*) 0 +select /*2-2*/ count(*) from performance_schema.events_transactions_history_long +where THREAD_ID = $con2_thread_id; count(*) 0 -"=========================== Transactions user 3" +########################### Transactions user 3 - 2 +select /*3-2*/ count(*) from performance_schema.events_transactions_current +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-2*/ count(*) from performance_schema.events_transactions_history +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-2*/ count(*) from performance_schema.events_transactions_history_long +where THREAD_ID = $con3_thread_id; count(*) 0 -"=========================== Transactions user 4" +########################### Transactions user 4 - 2 +select /*4-2*/ count(*) from performance_schema.events_transactions_current +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-2*/ count(*) from performance_schema.events_transactions_history +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-2*/ count(*) from performance_schema.events_transactions_history_long +where THREAD_ID = $con4_thread_id; count(*) 0 -"=========================== Statements user 1" +########################### Statements user 1 - 2 +select /*1-2*/ EVENT_NAME, SQL_TEXT from performance_schema.events_statements_current +where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME SQL_TEXT statement/sql/xa_commit XA COMMIT 'XA_CON1', 'XA_BQUAL', 12 +select /*1-2*/ count(*) from performance_schema.events_statements_history +where THREAD_ID = $con1_thread_id; count(*) 0 +select /*1-2*/ count(*) from performance_schema.events_statements_history_long +where THREAD_ID = $con1_thread_id; count(*) 0 -"=========================== Statements user 2" +########################### Statements user 2 - 2 +select /*2-2*/ EVENT_NAME, SQL_TEXT from performance_schema.events_statements_current +where THREAD_ID = $con2_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME SQL_TEXT statement/sql/xa_commit XA COMMIT 'XA_CON2', 'XA_BQUAL', 12 +select /*2-2*/ count(*) from performance_schema.events_statements_history +where THREAD_ID = $con2_thread_id; count(*) 0 +select /*2-2*/ count(*) from performance_schema.events_statements_history_long +where THREAD_ID = $con2_thread_id; count(*) 0 -"=========================== Statements user 3" +########################### Statements user 3 - 2 +select /*3-2*/ count(*) from performance_schema.events_statements_current +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-2*/ count(*) from performance_schema.events_statements_history +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-2*/ count(*) from performance_schema.events_statements_history_long +where THREAD_ID = $con3_thread_id; count(*) 0 -"=========================== Statements user 4" +########################### Statements user 4 - 2 +select /*4-2*/ count(*) from performance_schema.events_statements_current +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-2*/ count(*) from performance_schema.events_statements_history +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-2*/ count(*) from performance_schema.events_statements_history_long +where THREAD_ID = $con4_thread_id; count(*) 0 -"=========================== Stages user 1" +########################### Stages user 1 - 2 +select /*1-2*/ EVENT_NAME from performance_schema.events_stages_current +where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME +select /*1-2*/ count(*) from performance_schema.events_stages_history +where THREAD_ID = $con1_thread_id; count(*) 0 +select /*1-2*/ count(*) from performance_schema.events_stages_history_long +where THREAD_ID = $con1_thread_id; count(*) 0 -"=========================== Stages user 2" +########################### Stages user 2 - 2 +select /*2-2*/ EVENT_NAME from performance_schema.events_stages_current +where THREAD_ID = $con2_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME +select /*2-2*/ count(*) from performance_schema.events_stages_history +where THREAD_ID = $con2_thread_id; count(*) 0 +select /*2-2*/ count(*) from performance_schema.events_stages_history_long +where THREAD_ID = $con2_thread_id; count(*) 0 -"=========================== Stages user 3" +########################### Stages user 3 - 2 +select /*3-2*/ count(*) from performance_schema.events_stages_current +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-2*/ count(*) from performance_schema.events_stages_history +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-2*/ count(*) from performance_schema.events_stages_history_long +where THREAD_ID = $con3_thread_id; count(*) 0 -"=========================== Stages user 4" +########################### Stages user 4 - 2 +select /*4-2*/ count(*) from performance_schema.events_stages_current +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-2*/ count(*) from performance_schema.events_stages_history +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-2*/ count(*) from performance_schema.events_stages_history_long +where THREAD_ID = $con4_thread_id; count(*) 0 -"=========================== Waits user 1" +########################### Waits user 1 - 2 +select /*1-2*/ EVENT_NAME from performance_schema.events_waits_current +where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME idle +select /*1-2*/ count(*) as has_waits from performance_schema.events_waits_history +where THREAD_ID = $con1_thread_id; has_waits 0 +select /*1-2*/ count(*) as has_waits from performance_schema.events_waits_history_long +where THREAD_ID = $con1_thread_id; has_waits 0 -"=========================== Waits user 2" +########################### Waits user 2 - 2 +select /*2-2*/ EVENT_NAME from performance_schema.events_waits_current +where THREAD_ID = $con2_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME idle +select /*2-2*/ count(*) from performance_schema.events_waits_history +where THREAD_ID = $con2_thread_id; count(*) 0 +select /*2-2*/ count(*) from performance_schema.events_waits_history_long +where THREAD_ID = $con2_thread_id; count(*) 0 -"=========================== Waits user 3" +########################### Waits user 3 - 2 +select /*3-2*/ count(*) from performance_schema.events_waits_current +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-2*/ count(*) from performance_schema.events_waits_history +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-2*/ count(*) from performance_schema.events_waits_history_long +where THREAD_ID = $con3_thread_id; count(*) 0 -"=========================== Waits user 4" +########################### Waits user 4 - 2 +select /*4-2*/ count(*) from performance_schema.events_waits_current +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-2*/ count(*) from performance_schema.events_waits_history +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-2*/ count(*) from performance_schema.events_waits_history_long +where THREAD_ID = $con4_thread_id; count(*) 0 -# Switch to connection default, enable consumers connection default; update performance_schema.setup_consumers set enabled='YES' where name like "%history%"; @@ -476,7 +653,6 @@ truncate table performance_schema.events_stages_history_long; truncate table performance_schema.events_waits_current; truncate table performance_schema.events_waits_history; truncate table performance_schema.events_waits_history_long; -# Switch to connection con1 connection con1; XA START 'XA_CON1', 'XA_BQUAL', 12; select "Hi from con1"; @@ -485,7 +661,6 @@ Hi from con1 XA END 'XA_CON1', 'XA_BQUAL', 12; XA PREPARE 'XA_CON1', 'XA_BQUAL', 12; XA COMMIT 'XA_CON1', 'XA_BQUAL', 12; -# Switch to connection con2 connection con2; XA START 'XA_CON2', 'XA_BQUAL', 12; select "Hi from con2"; @@ -494,7 +669,6 @@ Hi from con2 XA END 'XA_CON2', 'XA_BQUAL', 12; XA PREPARE 'XA_CON2', 'XA_BQUAL', 12; XA COMMIT 'XA_CON2', 'XA_BQUAL', 12; -# Switch to connection con3 connection con3; XA START 'XA_CON3', 'XA_BQUAL', 12; select "Hi from con3"; @@ -503,7 +677,6 @@ Hi from con3 XA END 'XA_CON3', 'XA_BQUAL', 12; XA PREPARE 'XA_CON3', 'XA_BQUAL', 12; XA COMMIT 'XA_CON3', 'XA_BQUAL', 12; -# Switch to connection con4 connection con4; XA START 'XA_CON4', 'XA_BQUAL', 12; select "Hi from con4"; @@ -513,72 +686,124 @@ XA END 'XA_CON4', 'XA_BQUAL', 12; XA PREPARE 'XA_CON4', 'XA_BQUAL', 12; XA COMMIT 'XA_CON4', 'XA_BQUAL', 12; connection default; -"=========================== Transactions user 1" +########################### Transactions user 1 - 3 +select /*1-3*/ XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_current +where THREAD_ID = $con1_thread_id; XID_FORMAT_ID XID_GTRID XID_BQUAL 12 XA_CON1 XA_BQUAL +select /*1-3*/ XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_history +where THREAD_ID = $con1_thread_id; XID_FORMAT_ID XID_GTRID XID_BQUAL 12 XA_CON1 XA_BQUAL +select /*1-3*/ XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_history_long +where THREAD_ID = $con1_thread_id; XID_FORMAT_ID XID_GTRID XID_BQUAL 12 XA_CON1 XA_BQUAL -"=========================== Transactions user 2" +########################### Transactions user 2 - 3 +select /*2-3*/ XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_current +where THREAD_ID = $con2_thread_id; XID_FORMAT_ID XID_GTRID XID_BQUAL 12 XA_CON2 XA_BQUAL +select /*2-3*/ count(*) from performance_schema.events_transactions_history +where THREAD_ID = $con2_thread_id; count(*) 0 +select /*2-3*/ count(*) from performance_schema.events_transactions_history_long +where THREAD_ID = $con2_thread_id; count(*) 0 -"=========================== Transactions user 3" +########################### Transactions user 3 - 3 +select /*3-3*/ count(*) from performance_schema.events_transactions_current +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-3*/ count(*) from performance_schema.events_transactions_history +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-3*/ count(*) from performance_schema.events_transactions_history_long +where THREAD_ID = $con3_thread_id; count(*) 0 -"=========================== Transactions user 4" +########################### Transactions user 4 - 3 +select /*4-3*/ count(*) from performance_schema.events_transactions_current +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-3*/ count(*) from performance_schema.events_transactions_history +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-3*/ count(*) from performance_schema.events_transactions_history_long +where THREAD_ID = $con4_thread_id; count(*) 0 -"=========================== Statements user 1" +########################### Statements user 1 - 3 +select /*1-3*/ EVENT_NAME, SQL_TEXT from performance_schema.events_statements_current +where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME SQL_TEXT statement/sql/xa_commit XA COMMIT 'XA_CON1', 'XA_BQUAL', 12 +select /*1-3*/ EVENT_NAME, SQL_TEXT from performance_schema.events_statements_history +where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME SQL_TEXT statement/sql/xa_start XA START 'XA_CON1', 'XA_BQUAL', 12 statement/sql/select select "Hi from con1" statement/sql/xa_end XA END 'XA_CON1', 'XA_BQUAL', 12 statement/sql/xa_prepare XA PREPARE 'XA_CON1', 'XA_BQUAL', 12 statement/sql/xa_commit XA COMMIT 'XA_CON1', 'XA_BQUAL', 12 +select /*1-3*/ EVENT_NAME, SQL_TEXT from performance_schema.events_statements_history_long +where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME SQL_TEXT statement/sql/xa_start XA START 'XA_CON1', 'XA_BQUAL', 12 statement/sql/select select "Hi from con1" statement/sql/xa_end XA END 'XA_CON1', 'XA_BQUAL', 12 statement/sql/xa_prepare XA PREPARE 'XA_CON1', 'XA_BQUAL', 12 statement/sql/xa_commit XA COMMIT 'XA_CON1', 'XA_BQUAL', 12 -"=========================== Statements user 2" +########################### Statements user 2 - 3 +select /*2-3*/ EVENT_NAME, SQL_TEXT from performance_schema.events_statements_current +where THREAD_ID = $con2_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME SQL_TEXT statement/sql/xa_commit XA COMMIT 'XA_CON2', 'XA_BQUAL', 12 +select /*2-3*/ count(*) from performance_schema.events_statements_history +where THREAD_ID = $con2_thread_id; count(*) 0 +select /*2-3*/ count(*) from performance_schema.events_statements_history_long +where THREAD_ID = $con2_thread_id; count(*) 0 -"=========================== Statements user 3" +########################### Statements user 3 - 3 +select /*3-3*/ count(*) from performance_schema.events_statements_current +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-3*/ count(*) from performance_schema.events_statements_history +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-3*/ count(*) from performance_schema.events_statements_history_long +where THREAD_ID = $con3_thread_id; count(*) 0 -"=========================== Statements user 4" +########################### Statements user 4 - 3 +select /*4-3*/ count(*) from performance_schema.events_statements_current +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-3*/ count(*) from performance_schema.events_statements_history +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-3*/ count(*) from performance_schema.events_statements_history_long +where THREAD_ID = $con4_thread_id; count(*) 0 -"=========================== Stages user 1" +########################### Stages user 1 - 3 +select /*1-3*/ EVENT_NAME from performance_schema.events_stages_current +where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME +select /*1-3*/ EVENT_NAME from performance_schema.events_stages_history +where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME stage/sql/Starting cleanup stage/sql/Freeing items @@ -590,6 +815,8 @@ stage/sql/Query end stage/sql/Starting cleanup stage/sql/Freeing items stage/sql/Reset for next command +select /*1-3*/ EVENT_NAME from performance_schema.events_stages_history_long +where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME stage/sql/starting stage/sql/Query end @@ -633,55 +860,96 @@ stage/sql/Query end stage/sql/Starting cleanup stage/sql/Freeing items stage/sql/Reset for next command -"=========================== Stages user 2" +########################### Stages user 2 - 3 +select /*2-3*/ EVENT_NAME from performance_schema.events_stages_current +where THREAD_ID = $con2_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME +select /*2-3*/ count(*) from performance_schema.events_stages_history +where THREAD_ID = $con2_thread_id; count(*) 0 +select /*2-3*/ count(*) from performance_schema.events_stages_history_long +where THREAD_ID = $con2_thread_id; count(*) 0 -"=========================== Stages user 3" +########################### Stages user 3 - 3 +select /*3-3*/ count(*) from performance_schema.events_stages_current +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-3*/ count(*) from performance_schema.events_stages_history +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-3*/ count(*) from performance_schema.events_stages_history_long +where THREAD_ID = $con3_thread_id; count(*) 0 -"=========================== Stages user 4" +########################### Stages user 4 - 3 +select /*4-3*/ count(*) from performance_schema.events_stages_current +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-3*/ count(*) from performance_schema.events_stages_history +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-3*/ count(*) from performance_schema.events_stages_history_long +where THREAD_ID = $con4_thread_id; count(*) 0 -"=========================== Waits user 1" +########################### Waits user 1 - 3 +select /*1-3*/ EVENT_NAME from performance_schema.events_waits_current +where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME idle +select /*1-3*/ (count(*) > 5) as has_waits from performance_schema.events_waits_history +where THREAD_ID = $con1_thread_id; has_waits 1 +select /*1-3*/ (count(*) > 15) as has_waits from performance_schema.events_waits_history_long +where THREAD_ID = $con1_thread_id; has_waits 1 -"=========================== Waits user 2" +########################### Waits user 2 - 3 +select /*2-3*/ EVENT_NAME from performance_schema.events_waits_current +where THREAD_ID = $con2_thread_id order by THREAD_ID, EVENT_ID; EVENT_NAME idle +select /*2-3*/ count(*) from performance_schema.events_waits_history +where THREAD_ID = $con2_thread_id; count(*) 0 +select /*2-3*/ count(*) from performance_schema.events_waits_history_long +where THREAD_ID = $con2_thread_id; count(*) 0 -"=========================== Waits user 3" +########################### Waits user 3 - 3 +select /*3-3*/ count(*) from performance_schema.events_waits_current +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-3*/ count(*) from performance_schema.events_waits_history +where THREAD_ID = $con3_thread_id; count(*) 0 +select /*3-3*/ count(*) from performance_schema.events_waits_history_long +where THREAD_ID = $con3_thread_id; count(*) 0 -"=========================== Waits user 4" +########################### Waits user 4 - 3 +select /*4-3*/ count(*) from performance_schema.events_waits_current +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-3*/ count(*) from performance_schema.events_waits_history +where THREAD_ID = $con4_thread_id; count(*) 0 +select /*4-3*/ count(*) from performance_schema.events_waits_history_long +where THREAD_ID = $con4_thread_id; count(*) 0 -# Switch to connection default connection default; revoke all privileges, grant option from user1@localhost; revoke all privileges, grant option from user2@localhost; diff --git a/mysql-test/suite/perfschema/t/bad_option.test b/mysql-test/suite/perfschema/t/bad_option.test index 4feb0468e66..3eee669bdde 100644 --- a/mysql-test/suite/perfschema/t/bad_option.test +++ b/mysql-test/suite/perfschema/t/bad_option.test @@ -14,7 +14,7 @@ let $error_log= $MYSQLTEST_VARDIR/log/my_restart.err; let SEARCH_FILE= $error_log; # Stop the server let $restart_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect; ---exec echo "wait" > $restart_file +--write_line wait $restart_file --shutdown_server --source include/wait_until_disconnected.inc --error 7 @@ -62,7 +62,7 @@ let SEARCH_PATTERN= Can.t change dir to .*bad_option_h_param; --remove_file $error_log # Write file to make mysql-test-run.pl start up the server again ---exec echo "restart" > $restart_file +--write_line restart $restart_file # Turn on reconnect --enable_reconnect diff --git a/mysql-test/suite/perfschema/t/misc.test b/mysql-test/suite/perfschema/t/misc.test index 79c23c65616..e8b9691fda5 100644 --- a/mysql-test/suite/perfschema/t/misc.test +++ b/mysql-test/suite/perfschema/t/misc.test @@ -175,6 +175,7 @@ DROP TABLE t_60905; # show global variables like "performance_schema_max_thread_instances"; +replace_result 512 256; explain select * from performance_schema.threads; # diff --git a/mysql-test/suite/perfschema/t/processlist_57.test b/mysql-test/suite/perfschema/t/processlist_57.test index 748d8b7402b..fe8898ed049 100644 --- a/mysql-test/suite/perfschema/t/processlist_57.test +++ b/mysql-test/suite/perfschema/t/processlist_57.test @@ -23,7 +23,7 @@ DROP TABLE performance_schema.processlist; SHOW CREATE TABLE performance_schema.processlist; let $restart_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect; ---exec echo "wait" > $restart_file +--write_line wait $restart_file --echo ## --echo ## Server shutdown --echo ## @@ -93,7 +93,7 @@ SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST; --error ER_BAD_FIELD_ERROR SHOW PROCESSLIST; ---exec echo "wait" > $restart_file +--write_line wait $restart_file --echo ## --echo ## Server shutdown --echo ## @@ -166,7 +166,7 @@ SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST; # Works and returns no data, innodb table is empty. SHOW PROCESSLIST; ---exec echo "wait" > $restart_file +--write_line wait $restart_file --echo ## --echo ## Server shutdown --echo ## @@ -231,7 +231,7 @@ SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST; # Works and returns no data, innodb table is empty. SHOW PROCESSLIST; ---exec echo "wait" > $restart_file +--write_line wait $restart_file --echo ## --echo ## Server shutdown --echo ## @@ -306,7 +306,7 @@ SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST; --replace_column 3 [HOST:PORT] 6 [TIME] SHOW PROCESSLIST; ---exec echo "wait" > $restart_file +--write_line wait $restart_file --echo ## --echo ## Server shutdown --echo ## diff --git a/mysql-test/suite/perfschema/t/setup_instruments_defaults.test b/mysql-test/suite/perfschema/t/setup_instruments_defaults.test index ea59cd4f266..bd33c559d9a 100644 --- a/mysql-test/suite/perfschema/t/setup_instruments_defaults.test +++ b/mysql-test/suite/perfschema/t/setup_instruments_defaults.test @@ -69,7 +69,7 @@ SELECT * FROM performance_schema.setup_instruments WHERE name like "%wait/io/table/sql/handler%"; # Write file to make mysql-test-run.pl wait for the server to stop ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect # Restart the server --echo # @@ -79,7 +79,7 @@ WHERE name like "%wait/io/table/sql/handler%"; --echo # Restart server with wait/io/table/sql/handler disabled ---exec echo "restart:--loose-performance-schema-instrument=%wait/io/table/sql/%=off" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line "restart:--loose-performance-schema-instrument=%wait/io/table/sql/%=off" $MYSQLTEST_VARDIR/tmp/mysqld.1.expect # Turn on reconnect --echo # Enable reconnect diff --git a/mysql-test/suite/perfschema/t/statement_program_lost_inst.test b/mysql-test/suite/perfschema/t/statement_program_lost_inst.test index 023180b9d2b..0742043bba3 100644 --- a/mysql-test/suite/perfschema/t/statement_program_lost_inst.test +++ b/mysql-test/suite/perfschema/t/statement_program_lost_inst.test @@ -19,10 +19,10 @@ --source include/have_perfschema.inc let $restart_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect; ---exec echo "wait" > $restart_file +--write_line wait $restart_file --shutdown_server --source include/wait_until_disconnected.inc ---exec echo "restart:--performance_schema_max_program_instances=7 --performance_schema_max_statement_stack=2 --thread_stack=655360">$restart_file +--write_line "restart:--performance_schema_max_program_instances=7 --performance_schema_max_statement_stack=2 --thread_stack=655360" $restart_file --enable_reconnect --source include/wait_until_connected_again.inc diff --git a/mysql-test/suite/perfschema/t/threads_history.test b/mysql-test/suite/perfschema/t/threads_history.test index f42dd6d0ab4..aee983339d2 100644 --- a/mysql-test/suite/perfschema/t/threads_history.test +++ b/mysql-test/suite/perfschema/t/threads_history.test @@ -23,7 +23,6 @@ flush privileges; select * from performance_schema.setup_consumers; ---echo # Switch to (con1, localhost, user1, , ) connect (con1, localhost, user1, , ); update performance_schema.threads @@ -33,7 +32,6 @@ update performance_schema.threads let $con1_thread_id= `select THREAD_ID from performance_schema.threads where PROCESSLIST_ID = connection_id()`; ---echo # Switch to (con2, localhost, user2, , ) connect (con2, localhost, user2, , ); update performance_schema.threads @@ -43,7 +41,6 @@ update performance_schema.threads let $con2_thread_id= `select THREAD_ID from performance_schema.threads where PROCESSLIST_ID = connection_id()`; ---echo # Switch to (con3, localhost, user3, , ) connect (con3, localhost, user3, , ); update performance_schema.threads @@ -53,7 +50,6 @@ update performance_schema.threads let $con3_thread_id= `select THREAD_ID from performance_schema.threads where PROCESSLIST_ID = connection_id()`; ---echo # Switch to (con4, localhost, user4, , ) connect (con4, localhost, user4, , ); update performance_schema.threads @@ -63,7 +59,6 @@ update performance_schema.threads let $con4_thread_id= `select THREAD_ID from performance_schema.threads where PROCESSLIST_ID = connection_id()`; ---echo # Switch to connection default --connection default truncate table performance_schema.events_transactions_current; @@ -79,7 +74,6 @@ truncate table performance_schema.events_waits_current; truncate table performance_schema.events_waits_history; truncate table performance_schema.events_waits_history_long; ---echo # Switch to connection con1 --connection con1 XA START 'XA_CON1', 'XA_BQUAL', 12; @@ -88,7 +82,6 @@ XA END 'XA_CON1', 'XA_BQUAL', 12; XA PREPARE 'XA_CON1', 'XA_BQUAL', 12; XA COMMIT 'XA_CON1', 'XA_BQUAL', 12; ---echo # Switch to connection con2 --connection con2 XA START 'XA_CON2', 'XA_BQUAL', 12; @@ -97,7 +90,6 @@ XA END 'XA_CON2', 'XA_BQUAL', 12; XA PREPARE 'XA_CON2', 'XA_BQUAL', 12; XA COMMIT 'XA_CON2', 'XA_BQUAL', 12; ---echo # Switch to connection con3 --connection con3 XA START 'XA_CON3', 'XA_BQUAL', 12; @@ -106,7 +98,6 @@ XA END 'XA_CON3', 'XA_BQUAL', 12; XA PREPARE 'XA_CON3', 'XA_BQUAL', 12; XA COMMIT 'XA_CON3', 'XA_BQUAL', 12; ---echo # Switch to connection con4 --connection con4 XA START 'XA_CON4', 'XA_BQUAL', 12; @@ -117,165 +108,150 @@ XA COMMIT 'XA_CON4', 'XA_BQUAL', 12; --connection default ---disable_query_log +echo ########################### Transactions user 1 - 1; -echo "=========================== Transactions user 1"; - -eval select XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_current +evalp select /*1-1*/ XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_current where THREAD_ID = $con1_thread_id; -eval select XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_history +evalp select /*1-1*/ XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_history where THREAD_ID = $con1_thread_id; -eval select XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_history_long +evalp select /*1-1*/ XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_history_long where THREAD_ID = $con1_thread_id; -echo "=========================== Transactions user 2"; +echo ########################### Transactions user 2 - 1; -eval select XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_current +evalp select /*2-1*/ XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_current where THREAD_ID = $con2_thread_id; -eval select count(*) from performance_schema.events_transactions_history +evalp select /*2-1*/ count(*) from performance_schema.events_transactions_history where THREAD_ID = $con2_thread_id; -eval select count(*) from performance_schema.events_transactions_history_long +evalp select /*2-1*/ count(*) from performance_schema.events_transactions_history_long where THREAD_ID = $con2_thread_id; -echo "=========================== Transactions user 3"; +echo ########################### Transactions user 3 - 1; -eval select count(*) from performance_schema.events_transactions_current +evalp select /*3-1*/ count(*) from performance_schema.events_transactions_current where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_transactions_history +evalp select /*3-1*/ count(*) from performance_schema.events_transactions_history where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_transactions_history_long +evalp select /*3-1*/ count(*) from performance_schema.events_transactions_history_long where THREAD_ID = $con3_thread_id; -echo "=========================== Transactions user 4"; +echo ########################### Transactions user 4 - 1; -eval select count(*) from performance_schema.events_transactions_current +evalp select /*4-1*/ count(*) from performance_schema.events_transactions_current where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_transactions_history +evalp select /*4-1*/ count(*) from performance_schema.events_transactions_history where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_transactions_history_long +evalp select /*4-1*/ count(*) from performance_schema.events_transactions_history_long where THREAD_ID = $con4_thread_id; -echo "=========================== Statements user 1"; +echo ########################### Statements user 1 - 1; -eval select EVENT_NAME, SQL_TEXT from performance_schema.events_statements_current - where THREAD_ID = $con1_thread_id - order by THREAD_ID, EVENT_ID; -eval select EVENT_NAME, SQL_TEXT from performance_schema.events_statements_history - where THREAD_ID = $con1_thread_id - order by THREAD_ID, EVENT_ID; -eval select EVENT_NAME, SQL_TEXT from performance_schema.events_statements_history_long - where THREAD_ID = $con1_thread_id - order by THREAD_ID, EVENT_ID; +evalp select /*1-1*/ EVENT_NAME, SQL_TEXT from performance_schema.events_statements_current + where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*1-1*/ EVENT_NAME, SQL_TEXT from performance_schema.events_statements_history + where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*1-1*/ EVENT_NAME, SQL_TEXT from performance_schema.events_statements_history_long + where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; -echo "=========================== Statements user 2"; +echo ########################### Statements user 2 - 1; -eval select EVENT_NAME, SQL_TEXT from performance_schema.events_statements_current - where THREAD_ID = $con2_thread_id - order by THREAD_ID, EVENT_ID; -eval select count(*) from performance_schema.events_statements_history +evalp select /*2-1*/ EVENT_NAME, SQL_TEXT from performance_schema.events_statements_current + where THREAD_ID = $con2_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*2-1*/ count(*) from performance_schema.events_statements_history where THREAD_ID = $con2_thread_id; -eval select count(*) from performance_schema.events_statements_history_long +evalp select /*2-1*/ count(*) from performance_schema.events_statements_history_long where THREAD_ID = $con2_thread_id; -echo "=========================== Statements user 3"; +echo ########################### Statements user 3 - 1; -eval select count(*) from performance_schema.events_statements_current +evalp select /*3-1*/ count(*) from performance_schema.events_statements_current where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_statements_history +evalp select /*3-1*/ count(*) from performance_schema.events_statements_history where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_statements_history_long +evalp select /*3-1*/ count(*) from performance_schema.events_statements_history_long where THREAD_ID = $con3_thread_id; -echo "=========================== Statements user 4"; +echo ########################### Statements user 4 - 1; -eval select count(*) from performance_schema.events_statements_current +evalp select /*4-1*/ count(*) from performance_schema.events_statements_current where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_statements_history +evalp select /*4-1*/ count(*) from performance_schema.events_statements_history where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_statements_history_long +evalp select /*4-1*/ count(*) from performance_schema.events_statements_history_long where THREAD_ID = $con4_thread_id; -echo "=========================== Stages user 1"; +echo ########################### Stages user 1 - 1; -eval select EVENT_NAME from performance_schema.events_stages_current - where THREAD_ID = $con1_thread_id - order by THREAD_ID, EVENT_ID; -eval select EVENT_NAME from performance_schema.events_stages_history - where THREAD_ID = $con1_thread_id - order by THREAD_ID, EVENT_ID; -eval select EVENT_NAME from performance_schema.events_stages_history_long - where THREAD_ID = $con1_thread_id - order by THREAD_ID, EVENT_ID; +evalp select /*1-1*/ EVENT_NAME from performance_schema.events_stages_current + where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*1-1*/ EVENT_NAME from performance_schema.events_stages_history + where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*1-1*/ EVENT_NAME from performance_schema.events_stages_history_long + where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; -echo "=========================== Stages user 2"; +echo ########################### Stages user 2 - 1; -eval select EVENT_NAME from performance_schema.events_stages_current - where THREAD_ID = $con2_thread_id - order by THREAD_ID, EVENT_ID; -eval select count(*) from performance_schema.events_stages_history +evalp select /*2-1*/ EVENT_NAME from performance_schema.events_stages_current + where THREAD_ID = $con2_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*2-1*/ count(*) from performance_schema.events_stages_history where THREAD_ID = $con2_thread_id; -eval select count(*) from performance_schema.events_stages_history_long +evalp select /*2-1*/ count(*) from performance_schema.events_stages_history_long where THREAD_ID = $con2_thread_id; -echo "=========================== Stages user 3"; +echo ########################### Stages user 3 - 1; -eval select count(*) from performance_schema.events_stages_current +evalp select /*3-1*/ count(*) from performance_schema.events_stages_current where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_stages_history +evalp select /*3-1*/ count(*) from performance_schema.events_stages_history where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_stages_history_long +evalp select /*3-1*/ count(*) from performance_schema.events_stages_history_long where THREAD_ID = $con3_thread_id; -echo "=========================== Stages user 4"; +echo ########################### Stages user 4 - 1; -eval select count(*) from performance_schema.events_stages_current +evalp select /*4-1*/ count(*) from performance_schema.events_stages_current where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_stages_history +evalp select /*4-1*/ count(*) from performance_schema.events_stages_history where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_stages_history_long +evalp select /*4-1*/ count(*) from performance_schema.events_stages_history_long where THREAD_ID = $con4_thread_id; -echo "=========================== Waits user 1"; +echo ########################### Waits user 1 - 1; -eval select EVENT_NAME from performance_schema.events_waits_current - where THREAD_ID = $con1_thread_id - order by THREAD_ID, EVENT_ID; -eval select (count(*) > 5) as has_waits from performance_schema.events_waits_history +evalp select /*1-1*/ EVENT_NAME from performance_schema.events_waits_current + where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*1-1*/ (count(*) > 5) as has_waits from performance_schema.events_waits_history where THREAD_ID = $con1_thread_id; -eval select (count(*) > 15) as has_waits from performance_schema.events_waits_history_long +evalp select /*1-1*/ (count(*) > 15) as has_waits from performance_schema.events_waits_history_long where THREAD_ID = $con1_thread_id; -echo "=========================== Waits user 2"; +echo ########################### Waits user 2 - 1; -eval select EVENT_NAME from performance_schema.events_waits_current - where THREAD_ID = $con2_thread_id - order by THREAD_ID, EVENT_ID; -eval select count(*) from performance_schema.events_waits_history +evalp select /*2-1*/ EVENT_NAME from performance_schema.events_waits_current + where THREAD_ID = $con2_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*2-1*/ count(*) from performance_schema.events_waits_history where THREAD_ID = $con2_thread_id; -eval select count(*) from performance_schema.events_waits_history_long +evalp select /*2-1*/ count(*) from performance_schema.events_waits_history_long where THREAD_ID = $con2_thread_id; -echo "=========================== Waits user 3"; +echo ########################### Waits user 3 - 1; -eval select count(*) from performance_schema.events_waits_current +evalp select /*3-1*/ count(*) from performance_schema.events_waits_current where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_waits_history +evalp select /*3-1*/ count(*) from performance_schema.events_waits_history where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_waits_history_long +evalp select /*3-1*/ count(*) from performance_schema.events_waits_history_long where THREAD_ID = $con3_thread_id; -echo "=========================== Waits user 4"; +echo ########################### Waits user 4 - 1; -eval select count(*) from performance_schema.events_waits_current +evalp select /*4-1*/ count(*) from performance_schema.events_waits_current where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_waits_history +evalp select /*4-1*/ count(*) from performance_schema.events_waits_history where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_waits_history_long +evalp select /*4-1*/ count(*) from performance_schema.events_waits_history_long where THREAD_ID = $con4_thread_id; ---enable_query_log - ---echo # Switch to connection default, disable consumers --connection default update performance_schema.setup_consumers @@ -296,7 +272,6 @@ truncate table performance_schema.events_waits_current; truncate table performance_schema.events_waits_history; truncate table performance_schema.events_waits_history_long; ---echo # Switch to connection con1 --connection con1 XA START 'XA_CON1', 'XA_BQUAL', 12; @@ -305,7 +280,6 @@ XA END 'XA_CON1', 'XA_BQUAL', 12; XA PREPARE 'XA_CON1', 'XA_BQUAL', 12; XA COMMIT 'XA_CON1', 'XA_BQUAL', 12; ---echo # Switch to connection con2 --connection con2 XA START 'XA_CON2', 'XA_BQUAL', 12; @@ -314,7 +288,6 @@ XA END 'XA_CON2', 'XA_BQUAL', 12; XA PREPARE 'XA_CON2', 'XA_BQUAL', 12; XA COMMIT 'XA_CON2', 'XA_BQUAL', 12; ---echo # Switch to connection con3 --connection con3 XA START 'XA_CON3', 'XA_BQUAL', 12; @@ -323,7 +296,6 @@ XA END 'XA_CON3', 'XA_BQUAL', 12; XA PREPARE 'XA_CON3', 'XA_BQUAL', 12; XA COMMIT 'XA_CON3', 'XA_BQUAL', 12; ---echo # Switch to connection con4 --connection con4 XA START 'XA_CON4', 'XA_BQUAL', 12; @@ -334,161 +306,150 @@ XA COMMIT 'XA_CON4', 'XA_BQUAL', 12; --connection default ---disable_query_log +echo ########################### Transactions user 1 - 2; -echo "=========================== Transactions user 1"; - -eval select XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_current +evalp select /*1-2*/ XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_current where THREAD_ID = $con1_thread_id; -eval select count(*) from performance_schema.events_transactions_history +evalp select /*1-2*/ count(*) from performance_schema.events_transactions_history where THREAD_ID = $con1_thread_id; -eval select count(*) from performance_schema.events_transactions_history_long +evalp select /*1-2*/ count(*) from performance_schema.events_transactions_history_long where THREAD_ID = $con1_thread_id; -echo "=========================== Transactions user 2"; +echo ########################### Transactions user 2 - 2; -eval select XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_current +evalp select /*2-2*/ XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_current where THREAD_ID = $con2_thread_id; -eval select count(*) from performance_schema.events_transactions_history +evalp select /*2-2*/ count(*) from performance_schema.events_transactions_history where THREAD_ID = $con2_thread_id; -eval select count(*) from performance_schema.events_transactions_history_long +evalp select /*2-2*/ count(*) from performance_schema.events_transactions_history_long where THREAD_ID = $con2_thread_id; -echo "=========================== Transactions user 3"; +echo ########################### Transactions user 3 - 2; -eval select count(*) from performance_schema.events_transactions_current +evalp select /*3-2*/ count(*) from performance_schema.events_transactions_current where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_transactions_history +evalp select /*3-2*/ count(*) from performance_schema.events_transactions_history where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_transactions_history_long +evalp select /*3-2*/ count(*) from performance_schema.events_transactions_history_long where THREAD_ID = $con3_thread_id; -echo "=========================== Transactions user 4"; +echo ########################### Transactions user 4 - 2; -eval select count(*) from performance_schema.events_transactions_current +evalp select /*4-2*/ count(*) from performance_schema.events_transactions_current where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_transactions_history +evalp select /*4-2*/ count(*) from performance_schema.events_transactions_history where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_transactions_history_long +evalp select /*4-2*/ count(*) from performance_schema.events_transactions_history_long where THREAD_ID = $con4_thread_id; -echo "=========================== Statements user 1"; +echo ########################### Statements user 1 - 2; -eval select EVENT_NAME, SQL_TEXT from performance_schema.events_statements_current - where THREAD_ID = $con1_thread_id - order by THREAD_ID, EVENT_ID; -eval select count(*) from performance_schema.events_statements_history +evalp select /*1-2*/ EVENT_NAME, SQL_TEXT from performance_schema.events_statements_current + where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*1-2*/ count(*) from performance_schema.events_statements_history where THREAD_ID = $con1_thread_id; -eval select count(*) from performance_schema.events_statements_history_long +evalp select /*1-2*/ count(*) from performance_schema.events_statements_history_long where THREAD_ID = $con1_thread_id; -echo "=========================== Statements user 2"; +echo ########################### Statements user 2 - 2; -eval select EVENT_NAME, SQL_TEXT from performance_schema.events_statements_current - where THREAD_ID = $con2_thread_id - order by THREAD_ID, EVENT_ID; -eval select count(*) from performance_schema.events_statements_history +evalp select /*2-2*/ EVENT_NAME, SQL_TEXT from performance_schema.events_statements_current + where THREAD_ID = $con2_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*2-2*/ count(*) from performance_schema.events_statements_history where THREAD_ID = $con2_thread_id; -eval select count(*) from performance_schema.events_statements_history_long +evalp select /*2-2*/ count(*) from performance_schema.events_statements_history_long where THREAD_ID = $con2_thread_id; -echo "=========================== Statements user 3"; +echo ########################### Statements user 3 - 2; -eval select count(*) from performance_schema.events_statements_current +evalp select /*3-2*/ count(*) from performance_schema.events_statements_current where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_statements_history +evalp select /*3-2*/ count(*) from performance_schema.events_statements_history where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_statements_history_long +evalp select /*3-2*/ count(*) from performance_schema.events_statements_history_long where THREAD_ID = $con3_thread_id; -echo "=========================== Statements user 4"; +echo ########################### Statements user 4 - 2; -eval select count(*) from performance_schema.events_statements_current +evalp select /*4-2*/ count(*) from performance_schema.events_statements_current where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_statements_history +evalp select /*4-2*/ count(*) from performance_schema.events_statements_history where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_statements_history_long +evalp select /*4-2*/ count(*) from performance_schema.events_statements_history_long where THREAD_ID = $con4_thread_id; -echo "=========================== Stages user 1"; +echo ########################### Stages user 1 - 2; -eval select EVENT_NAME from performance_schema.events_stages_current - where THREAD_ID = $con1_thread_id - order by THREAD_ID, EVENT_ID; -eval select count(*) from performance_schema.events_stages_history +evalp select /*1-2*/ EVENT_NAME from performance_schema.events_stages_current + where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*1-2*/ count(*) from performance_schema.events_stages_history where THREAD_ID = $con1_thread_id; -eval select count(*) from performance_schema.events_stages_history_long +evalp select /*1-2*/ count(*) from performance_schema.events_stages_history_long where THREAD_ID = $con1_thread_id; -echo "=========================== Stages user 2"; +echo ########################### Stages user 2 - 2; -eval select EVENT_NAME from performance_schema.events_stages_current - where THREAD_ID = $con2_thread_id - order by THREAD_ID, EVENT_ID; -eval select count(*) from performance_schema.events_stages_history +evalp select /*2-2*/ EVENT_NAME from performance_schema.events_stages_current + where THREAD_ID = $con2_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*2-2*/ count(*) from performance_schema.events_stages_history where THREAD_ID = $con2_thread_id; -eval select count(*) from performance_schema.events_stages_history_long +evalp select /*2-2*/ count(*) from performance_schema.events_stages_history_long where THREAD_ID = $con2_thread_id; -echo "=========================== Stages user 3"; +echo ########################### Stages user 3 - 2; -eval select count(*) from performance_schema.events_stages_current +evalp select /*3-2*/ count(*) from performance_schema.events_stages_current where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_stages_history +evalp select /*3-2*/ count(*) from performance_schema.events_stages_history where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_stages_history_long +evalp select /*3-2*/ count(*) from performance_schema.events_stages_history_long where THREAD_ID = $con3_thread_id; -echo "=========================== Stages user 4"; +echo ########################### Stages user 4 - 2; -eval select count(*) from performance_schema.events_stages_current +evalp select /*4-2*/ count(*) from performance_schema.events_stages_current where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_stages_history +evalp select /*4-2*/ count(*) from performance_schema.events_stages_history where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_stages_history_long +evalp select /*4-2*/ count(*) from performance_schema.events_stages_history_long where THREAD_ID = $con4_thread_id; -echo "=========================== Waits user 1"; +echo ########################### Waits user 1 - 2; -eval select EVENT_NAME from performance_schema.events_waits_current - where THREAD_ID = $con1_thread_id - order by THREAD_ID, EVENT_ID; -eval select count(*) as has_waits from performance_schema.events_waits_history +evalp select /*1-2*/ EVENT_NAME from performance_schema.events_waits_current + where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*1-2*/ count(*) as has_waits from performance_schema.events_waits_history where THREAD_ID = $con1_thread_id; -eval select count(*) as has_waits from performance_schema.events_waits_history_long +evalp select /*1-2*/ count(*) as has_waits from performance_schema.events_waits_history_long where THREAD_ID = $con1_thread_id; -echo "=========================== Waits user 2"; +echo ########################### Waits user 2 - 2; -eval select EVENT_NAME from performance_schema.events_waits_current - where THREAD_ID = $con2_thread_id - order by THREAD_ID, EVENT_ID; -eval select count(*) from performance_schema.events_waits_history +evalp select /*2-2*/ EVENT_NAME from performance_schema.events_waits_current + where THREAD_ID = $con2_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*2-2*/ count(*) from performance_schema.events_waits_history where THREAD_ID = $con2_thread_id; -eval select count(*) from performance_schema.events_waits_history_long +evalp select /*2-2*/ count(*) from performance_schema.events_waits_history_long where THREAD_ID = $con2_thread_id; -echo "=========================== Waits user 3"; +echo ########################### Waits user 3 - 2; -eval select count(*) from performance_schema.events_waits_current +evalp select /*3-2*/ count(*) from performance_schema.events_waits_current where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_waits_history +evalp select /*3-2*/ count(*) from performance_schema.events_waits_history where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_waits_history_long +evalp select /*3-2*/ count(*) from performance_schema.events_waits_history_long where THREAD_ID = $con3_thread_id; -echo "=========================== Waits user 4"; +echo ########################### Waits user 4 - 2; -eval select count(*) from performance_schema.events_waits_current +evalp select /*4-2*/ count(*) from performance_schema.events_waits_current where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_waits_history +evalp select /*4-2*/ count(*) from performance_schema.events_waits_history where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_waits_history_long +evalp select /*4-2*/ count(*) from performance_schema.events_waits_history_long where THREAD_ID = $con4_thread_id; ---enable_query_log - ---echo # Switch to connection default, enable consumers --connection default update performance_schema.setup_consumers @@ -509,7 +470,6 @@ truncate table performance_schema.events_waits_current; truncate table performance_schema.events_waits_history; truncate table performance_schema.events_waits_history_long; ---echo # Switch to connection con1 --connection con1 XA START 'XA_CON1', 'XA_BQUAL', 12; @@ -518,7 +478,6 @@ XA END 'XA_CON1', 'XA_BQUAL', 12; XA PREPARE 'XA_CON1', 'XA_BQUAL', 12; XA COMMIT 'XA_CON1', 'XA_BQUAL', 12; ---echo # Switch to connection con2 --connection con2 XA START 'XA_CON2', 'XA_BQUAL', 12; @@ -527,7 +486,6 @@ XA END 'XA_CON2', 'XA_BQUAL', 12; XA PREPARE 'XA_CON2', 'XA_BQUAL', 12; XA COMMIT 'XA_CON2', 'XA_BQUAL', 12; ---echo # Switch to connection con3 --connection con3 XA START 'XA_CON3', 'XA_BQUAL', 12; @@ -536,7 +494,6 @@ XA END 'XA_CON3', 'XA_BQUAL', 12; XA PREPARE 'XA_CON3', 'XA_BQUAL', 12; XA COMMIT 'XA_CON3', 'XA_BQUAL', 12; ---echo # Switch to connection con4 --connection con4 XA START 'XA_CON4', 'XA_BQUAL', 12; @@ -547,165 +504,150 @@ XA COMMIT 'XA_CON4', 'XA_BQUAL', 12; --connection default ---disable_query_log +echo ########################### Transactions user 1 - 3; -echo "=========================== Transactions user 1"; - -eval select XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_current +evalp select /*1-3*/ XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_current where THREAD_ID = $con1_thread_id; -eval select XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_history +evalp select /*1-3*/ XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_history where THREAD_ID = $con1_thread_id; -eval select XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_history_long +evalp select /*1-3*/ XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_history_long where THREAD_ID = $con1_thread_id; -echo "=========================== Transactions user 2"; +echo ########################### Transactions user 2 - 3; -eval select XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_current +evalp select /*2-3*/ XID_FORMAT_ID, XID_GTRID, XID_BQUAL from performance_schema.events_transactions_current where THREAD_ID = $con2_thread_id; -eval select count(*) from performance_schema.events_transactions_history +evalp select /*2-3*/ count(*) from performance_schema.events_transactions_history where THREAD_ID = $con2_thread_id; -eval select count(*) from performance_schema.events_transactions_history_long +evalp select /*2-3*/ count(*) from performance_schema.events_transactions_history_long where THREAD_ID = $con2_thread_id; -echo "=========================== Transactions user 3"; +echo ########################### Transactions user 3 - 3; -eval select count(*) from performance_schema.events_transactions_current +evalp select /*3-3*/ count(*) from performance_schema.events_transactions_current where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_transactions_history +evalp select /*3-3*/ count(*) from performance_schema.events_transactions_history where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_transactions_history_long +evalp select /*3-3*/ count(*) from performance_schema.events_transactions_history_long where THREAD_ID = $con3_thread_id; -echo "=========================== Transactions user 4"; +echo ########################### Transactions user 4 - 3; -eval select count(*) from performance_schema.events_transactions_current +evalp select /*4-3*/ count(*) from performance_schema.events_transactions_current where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_transactions_history +evalp select /*4-3*/ count(*) from performance_schema.events_transactions_history where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_transactions_history_long +evalp select /*4-3*/ count(*) from performance_schema.events_transactions_history_long where THREAD_ID = $con4_thread_id; -echo "=========================== Statements user 1"; +echo ########################### Statements user 1 - 3; -eval select EVENT_NAME, SQL_TEXT from performance_schema.events_statements_current - where THREAD_ID = $con1_thread_id - order by THREAD_ID, EVENT_ID; -eval select EVENT_NAME, SQL_TEXT from performance_schema.events_statements_history - where THREAD_ID = $con1_thread_id - order by THREAD_ID, EVENT_ID; -eval select EVENT_NAME, SQL_TEXT from performance_schema.events_statements_history_long - where THREAD_ID = $con1_thread_id - order by THREAD_ID, EVENT_ID; +evalp select /*1-3*/ EVENT_NAME, SQL_TEXT from performance_schema.events_statements_current + where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*1-3*/ EVENT_NAME, SQL_TEXT from performance_schema.events_statements_history + where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*1-3*/ EVENT_NAME, SQL_TEXT from performance_schema.events_statements_history_long + where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; -echo "=========================== Statements user 2"; +echo ########################### Statements user 2 - 3; -eval select EVENT_NAME, SQL_TEXT from performance_schema.events_statements_current - where THREAD_ID = $con2_thread_id - order by THREAD_ID, EVENT_ID; -eval select count(*) from performance_schema.events_statements_history +evalp select /*2-3*/ EVENT_NAME, SQL_TEXT from performance_schema.events_statements_current + where THREAD_ID = $con2_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*2-3*/ count(*) from performance_schema.events_statements_history where THREAD_ID = $con2_thread_id; -eval select count(*) from performance_schema.events_statements_history_long +evalp select /*2-3*/ count(*) from performance_schema.events_statements_history_long where THREAD_ID = $con2_thread_id; -echo "=========================== Statements user 3"; +echo ########################### Statements user 3 - 3; -eval select count(*) from performance_schema.events_statements_current +evalp select /*3-3*/ count(*) from performance_schema.events_statements_current where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_statements_history +evalp select /*3-3*/ count(*) from performance_schema.events_statements_history where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_statements_history_long +evalp select /*3-3*/ count(*) from performance_schema.events_statements_history_long where THREAD_ID = $con3_thread_id; -echo "=========================== Statements user 4"; +echo ########################### Statements user 4 - 3; -eval select count(*) from performance_schema.events_statements_current +evalp select /*4-3*/ count(*) from performance_schema.events_statements_current where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_statements_history +evalp select /*4-3*/ count(*) from performance_schema.events_statements_history where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_statements_history_long +evalp select /*4-3*/ count(*) from performance_schema.events_statements_history_long where THREAD_ID = $con4_thread_id; -echo "=========================== Stages user 1"; +echo ########################### Stages user 1 - 3; -eval select EVENT_NAME from performance_schema.events_stages_current - where THREAD_ID = $con1_thread_id - order by THREAD_ID, EVENT_ID; -eval select EVENT_NAME from performance_schema.events_stages_history - where THREAD_ID = $con1_thread_id - order by THREAD_ID, EVENT_ID; -eval select EVENT_NAME from performance_schema.events_stages_history_long - where THREAD_ID = $con1_thread_id - order by THREAD_ID, EVENT_ID; +evalp select /*1-3*/ EVENT_NAME from performance_schema.events_stages_current + where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*1-3*/ EVENT_NAME from performance_schema.events_stages_history + where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*1-3*/ EVENT_NAME from performance_schema.events_stages_history_long + where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; -echo "=========================== Stages user 2"; +echo ########################### Stages user 2 - 3; -eval select EVENT_NAME from performance_schema.events_stages_current - where THREAD_ID = $con2_thread_id - order by THREAD_ID, EVENT_ID; -eval select count(*) from performance_schema.events_stages_history +evalp select /*2-3*/ EVENT_NAME from performance_schema.events_stages_current + where THREAD_ID = $con2_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*2-3*/ count(*) from performance_schema.events_stages_history where THREAD_ID = $con2_thread_id; -eval select count(*) from performance_schema.events_stages_history_long +evalp select /*2-3*/ count(*) from performance_schema.events_stages_history_long where THREAD_ID = $con2_thread_id; -echo "=========================== Stages user 3"; +echo ########################### Stages user 3 - 3; -eval select count(*) from performance_schema.events_stages_current +evalp select /*3-3*/ count(*) from performance_schema.events_stages_current where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_stages_history +evalp select /*3-3*/ count(*) from performance_schema.events_stages_history where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_stages_history_long +evalp select /*3-3*/ count(*) from performance_schema.events_stages_history_long where THREAD_ID = $con3_thread_id; -echo "=========================== Stages user 4"; +echo ########################### Stages user 4 - 3; -eval select count(*) from performance_schema.events_stages_current +evalp select /*4-3*/ count(*) from performance_schema.events_stages_current where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_stages_history +evalp select /*4-3*/ count(*) from performance_schema.events_stages_history where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_stages_history_long +evalp select /*4-3*/ count(*) from performance_schema.events_stages_history_long where THREAD_ID = $con4_thread_id; -echo "=========================== Waits user 1"; +echo ########################### Waits user 1 - 3; -eval select EVENT_NAME from performance_schema.events_waits_current - where THREAD_ID = $con1_thread_id - order by THREAD_ID, EVENT_ID; -eval select (count(*) > 5) as has_waits from performance_schema.events_waits_history +evalp select /*1-3*/ EVENT_NAME from performance_schema.events_waits_current + where THREAD_ID = $con1_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*1-3*/ (count(*) > 5) as has_waits from performance_schema.events_waits_history where THREAD_ID = $con1_thread_id; -eval select (count(*) > 15) as has_waits from performance_schema.events_waits_history_long +evalp select /*1-3*/ (count(*) > 15) as has_waits from performance_schema.events_waits_history_long where THREAD_ID = $con1_thread_id; -echo "=========================== Waits user 2"; +echo ########################### Waits user 2 - 3; -eval select EVENT_NAME from performance_schema.events_waits_current - where THREAD_ID = $con2_thread_id - order by THREAD_ID, EVENT_ID; -eval select count(*) from performance_schema.events_waits_history +evalp select /*2-3*/ EVENT_NAME from performance_schema.events_waits_current + where THREAD_ID = $con2_thread_id order by THREAD_ID, EVENT_ID; +evalp select /*2-3*/ count(*) from performance_schema.events_waits_history where THREAD_ID = $con2_thread_id; -eval select count(*) from performance_schema.events_waits_history_long +evalp select /*2-3*/ count(*) from performance_schema.events_waits_history_long where THREAD_ID = $con2_thread_id; -echo "=========================== Waits user 3"; +echo ########################### Waits user 3 - 3; -eval select count(*) from performance_schema.events_waits_current +evalp select /*3-3*/ count(*) from performance_schema.events_waits_current where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_waits_history +evalp select /*3-3*/ count(*) from performance_schema.events_waits_history where THREAD_ID = $con3_thread_id; -eval select count(*) from performance_schema.events_waits_history_long +evalp select /*3-3*/ count(*) from performance_schema.events_waits_history_long where THREAD_ID = $con3_thread_id; -echo "=========================== Waits user 4"; +echo ########################### Waits user 4 - 3; -eval select count(*) from performance_schema.events_waits_current +evalp select /*4-3*/ count(*) from performance_schema.events_waits_current where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_waits_history +evalp select /*4-3*/ count(*) from performance_schema.events_waits_history where THREAD_ID = $con4_thread_id; -eval select count(*) from performance_schema.events_waits_history_long +evalp select /*4-3*/ count(*) from performance_schema.events_waits_history_long where THREAD_ID = $con4_thread_id; ---enable_query_log - ---echo # Switch to connection default --connection default revoke all privileges, grant option from user1@localhost; diff --git a/mysql-test/suite/rpl/r/parallel_backup.result b/mysql-test/suite/rpl/r/parallel_backup.result index 83c7a916c13..361838927e9 100644 --- a/mysql-test/suite/rpl/r/parallel_backup.result +++ b/mysql-test/suite/rpl/r/parallel_backup.result @@ -125,7 +125,7 @@ include/save_master_gtid.inc connection slave; SET @sav_innodb_lock_wait_timeout = @@global.innodb_lock_wait_timeout; SET @sav_slave_transaction_retries = @@global.slave_transaction_retries; -SET @@global.innodb_lock_wait_timeout =1; +SET @@global.innodb_lock_wait_timeout =5; SET @@global.slave_transaction_retries=0; include/start_slave.inc connection aux_slave; @@ -168,7 +168,7 @@ include/save_master_gtid.inc connection slave; SET @sav_innodb_lock_wait_timeout = @@global.innodb_lock_wait_timeout; SET @sav_slave_transaction_retries = @@global.slave_transaction_retries; -SET @@global.innodb_lock_wait_timeout =1; +SET @@global.innodb_lock_wait_timeout =5; SET @@global.slave_transaction_retries=0; include/start_slave.inc connection aux_slave; diff --git a/mysql-test/suite/rpl/r/parallel_backup_lsu_off.result b/mysql-test/suite/rpl/r/parallel_backup_lsu_off.result index e1fd7701fcc..08955a77291 100644 --- a/mysql-test/suite/rpl/r/parallel_backup_lsu_off.result +++ b/mysql-test/suite/rpl/r/parallel_backup_lsu_off.result @@ -128,7 +128,7 @@ include/save_master_gtid.inc connection slave; SET @sav_innodb_lock_wait_timeout = @@global.innodb_lock_wait_timeout; SET @sav_slave_transaction_retries = @@global.slave_transaction_retries; -SET @@global.innodb_lock_wait_timeout =1; +SET @@global.innodb_lock_wait_timeout =5; SET @@global.slave_transaction_retries=0; include/start_slave.inc connection aux_slave; @@ -171,7 +171,7 @@ include/save_master_gtid.inc connection slave; SET @sav_innodb_lock_wait_timeout = @@global.innodb_lock_wait_timeout; SET @sav_slave_transaction_retries = @@global.slave_transaction_retries; -SET @@global.innodb_lock_wait_timeout =1; +SET @@global.innodb_lock_wait_timeout =5; SET @@global.slave_transaction_retries=0; include/start_slave.inc connection aux_slave; diff --git a/mysql-test/suite/rpl/r/parallel_backup_slave_binlog_off.result b/mysql-test/suite/rpl/r/parallel_backup_slave_binlog_off.result index 9e29e5a3875..bb00bf9cbf5 100644 --- a/mysql-test/suite/rpl/r/parallel_backup_slave_binlog_off.result +++ b/mysql-test/suite/rpl/r/parallel_backup_slave_binlog_off.result @@ -128,7 +128,7 @@ include/save_master_gtid.inc connection slave; SET @sav_innodb_lock_wait_timeout = @@global.innodb_lock_wait_timeout; SET @sav_slave_transaction_retries = @@global.slave_transaction_retries; -SET @@global.innodb_lock_wait_timeout =1; +SET @@global.innodb_lock_wait_timeout =5; SET @@global.slave_transaction_retries=0; include/start_slave.inc connection aux_slave; @@ -171,7 +171,7 @@ include/save_master_gtid.inc connection slave; SET @sav_innodb_lock_wait_timeout = @@global.innodb_lock_wait_timeout; SET @sav_slave_transaction_retries = @@global.slave_transaction_retries; -SET @@global.innodb_lock_wait_timeout =1; +SET @@global.innodb_lock_wait_timeout =5; SET @@global.slave_transaction_retries=0; include/start_slave.inc connection aux_slave; diff --git a/mysql-test/suite/rpl/r/rpl_domain_id_filter_restart.result b/mysql-test/suite/rpl/r/rpl_domain_id_filter_restart.result index f6eff3f9efc..948b4f48737 100644 --- a/mysql-test/suite/rpl/r/rpl_domain_id_filter_restart.result +++ b/mysql-test/suite/rpl/r/rpl_domain_id_filter_restart.result @@ -21,8 +21,9 @@ INSERT INTO t2 VALUES(1); SELECT * FROM t2; i 1 +include/save_master_gtid.inc connection slave; -connection slave; +include/sync_with_master_gtid.inc SELECT * FROM t1; i 1 diff --git a/mysql-test/suite/rpl/r/rpl_gtid_header_valid.result b/mysql-test/suite/rpl/r/rpl_gtid_header_valid.result new file mode 100644 index 00000000000..fd440feb3c9 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_gtid_header_valid.result @@ -0,0 +1,122 @@ +include/master-slave.inc +[connection master] +# +# Initialize test data +connection master; +create table t1 (a int) engine=innodb; +include/save_master_gtid.inc +set @@SESSION.debug_dbug= "+d,binlog_force_commit_id"; +connection slave; +set SQL_LOG_BIN= 0; +call mtr.add_suppression('Found invalid event in binary log'); +call mtr.add_suppression('Slave SQL.*Relay log read failure: Could not parse relay log event entry.* 1594'); +set SQL_LOG_BIN= 1; +include/sync_with_master_gtid.inc +include/stop_slave.inc +include/start_slave.inc +# +# Test FL_PREPARED_XA +connection master; +set @@SESSION.debug_dbug= "+d,negate_xid_from_gtid"; +set @commit_id= 100; +XA START 'x1'; +insert into t1 values (1); +XA END 'x1'; +XA PREPARE 'x1'; +set @@SESSION.debug_dbug= "-d,negate_xid_from_gtid"; +XA COMMIT 'x1'; +include/save_master_gtid.inc +# Waiting for slave to find invalid event.. +connection slave; +include/wait_for_slave_sql_error.inc [errno=1594] +STOP SLAVE IO_THREAD; +# Reset master binlogs (as there is an invalid event) and slave state +connection master; +RESET MASTER; +connection slave; +RESET MASTER; +RESET SLAVE; +set @@global.gtid_slave_pos=""; +include/start_slave.inc +# +# Test FL_COMPLETED_XA +connection master; +set @commit_id= 101; +XA START 'x1'; +insert into t1 values (2); +XA END 'x1'; +XA PREPARE 'x1'; +set @@SESSION.debug_dbug= "+d,negate_xid_from_gtid"; +XA COMMIT 'x1'; +set @@SESSION.debug_dbug= "-d,negate_xid_from_gtid"; +include/save_master_gtid.inc +# Waiting for slave to find invalid event.. +connection slave; +include/wait_for_slave_sql_error.inc [errno=1594] +STOP SLAVE IO_THREAD; +# Cleanup hanging XA PREPARE on slave +set statement SQL_LOG_BIN=0 for XA COMMIT 'x1'; +# Reset master binlogs (as there is an invalid event) and slave state +connection master; +RESET MASTER; +connection slave; +RESET MASTER; +RESET SLAVE; +set @@global.gtid_slave_pos=""; +include/start_slave.inc +# +# Test Missing xid.data (but has format id and length description parts) +connection master; +set @commit_id= 101; +XA START 'x1'; +insert into t1 values (1); +XA END 'x1'; +XA PREPARE 'x1'; +set @@SESSION.debug_dbug= "+d,negate_xid_data_from_gtid"; +XA COMMIT 'x1'; +set @@SESSION.debug_dbug= "-d,negate_xid_data_from_gtid"; +include/save_master_gtid.inc +# Waiting for slave to find invalid event.. +connection slave; +include/wait_for_slave_sql_error.inc [errno=1594] +STOP SLAVE IO_THREAD; +# Cleanup hanging XA PREPARE on slave +set statement SQL_LOG_BIN=0 for XA COMMIT 'x1'; +# Reset master binlogs (as there is an invalid event) and slave state +connection master; +RESET MASTER; +connection slave; +RESET MASTER; +RESET SLAVE; +set @@global.gtid_slave_pos=""; +include/start_slave.inc +# +# Test FL_EXTRA_MULTI_ENGINE +connection master; +set @old_dbug= @@SESSION.debug_dbug; +set @@SESSION.debug_dbug= "+d,inject_fl_extra_multi_engine_into_gtid"; +set @commit_id= 102; +insert into t1 values (3); +include/save_master_gtid.inc +set @@SESSION.debug_dbug=@old_dbug; +connection slave; +# Waiting for slave to find invalid event.. +include/wait_for_slave_sql_error.inc [errno=1594] +STOP SLAVE IO_THREAD; +# Reset master binlogs (as there is an invalid event) and slave state +connection master; +RESET MASTER; +connection slave; +RESET SLAVE; +RESET MASTER; +set @@global.gtid_slave_pos=""; +include/start_slave.inc +# +# Cleanup +connection master; +drop table t1; +include/save_master_gtid.inc +connection slave; +include/sync_with_master_gtid.inc +include/rpl_end.inc +# End of rpl_gtid_header_valid.test diff --git a/mysql-test/suite/rpl/r/rpl_mysql_manager_race_condition.result b/mysql-test/suite/rpl/r/rpl_mysql_manager_race_condition.result index 1172d8e39a9..740d1ddfcfa 100644 --- a/mysql-test/suite/rpl/r/rpl_mysql_manager_race_condition.result +++ b/mysql-test/suite/rpl/r/rpl_mysql_manager_race_condition.result @@ -17,6 +17,36 @@ include/sync_with_master_gtid.inc include/rpl_restart_server.inc [server_number=2 parameters: --debug_dbug="+d,delay_start_handle_manager"] include/start_slave.inc # +# MDEV-33799 +# Ensure that when the binary log is used for recovery (as tc log), that +# the recovery process cannot start the binlog background thread before +# the mysql handle manager has started. +connection slave; +# Add test suppresssions so crash recovery messages don't fail the test +set session sql_log_bin=0; +call mtr.add_suppression("mariadbd: Got error '145.*"); +call mtr.add_suppression("Checking table:.*"); +call mtr.add_suppression("mysql.gtid_slave_pos:.*hasn't closed the table properly"); +call mtr.add_suppression("Can't init tc log"); +call mtr.add_suppression("Aborting"); +set session sql_log_bin=1; +# Create slave-side only table +create table t2 (a int) engine=innodb; +# Crash mariadbd when binlogging transaction to corrupt database state +connection slave1; +set @@session.debug_dbug="+d,crash_before_writing_xid"; +insert into t2 values (1); +connection slave; +connection slave1; +Got one of the listed errors +# Restart mariadbd in recovery mode. Note --tc-heuristic-recover +# forces mysqld to exit with error, so we run mariadbd via CLI +# MYSQLD_LAST_CMD --debug_dbug="+d,delay_start_handle_manager" --tc-heuristic-recover=COMMIT +connection server_2; +connection slave1; +connection slave; +include/start_slave.inc +# # Cleanup # connection master; @@ -24,4 +54,5 @@ drop table t1; include/save_master_gtid.inc connection slave; include/sync_with_master_gtid.inc +drop table t2; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_parallel_multi_domain_xa.result b/mysql-test/suite/rpl/r/rpl_parallel_multi_domain_xa.result new file mode 100644 index 00000000000..defab6aef52 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_parallel_multi_domain_xa.result @@ -0,0 +1,55 @@ +include/master-slave.inc +[connection master] +call mtr.add_suppression("Deadlock found when trying to get lock; try restarting transaction"); +call mtr.add_suppression("WSREP: handlerton rollback failed"); +connection master; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +connection slave; +include/stop_slave.inc +SET @old_parallel_threads = @@GLOBAL.slave_parallel_threads; +SET @old_slave_domain_parallel_threads = @@GLOBAL.slave_domain_parallel_threads; +SET @@global.slave_parallel_threads = 5; +SET @@global.slave_domain_parallel_threads = 3; +SET @old_parallel_mode = @@GLOBAL.slave_parallel_mode; +CHANGE MASTER TO master_use_gtid=slave_pos; +connection master; +CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 0); +include/save_master_gtid.inc +connection slave; +include/start_slave.inc +include/sync_with_master_gtid.inc +include/stop_slave.inc +SET @@global.slave_parallel_mode ='optimistic'; +connection master; +include/save_master_gtid.inc +connection slave; +include/start_slave.inc +include/sync_with_master_gtid.inc +include/stop_slave.inc +connection master; +include/save_master_gtid.inc +connection slave; +SET @@global.slave_parallel_mode ='conservative'; +include/start_slave.inc +include/sync_with_master_gtid.inc +include/stop_slave.inc +include/save_master_gtid.inc +connection slave; +SET @@global.slave_parallel_mode = 'optimistic'; +include/start_slave.inc +include/sync_with_master_gtid.inc +include/diff_tables.inc [master:t1, slave:t1] +connection slave; +include/stop_slave.inc +SET @@global.slave_parallel_mode = @old_parallel_mode; +SET @@global.slave_parallel_threads = @old_parallel_threads; +SET @@global.slave_domain_parallel_threads = @old_slave_domain_parallel_threads; +include/start_slave.inc +connection master; +DROP TABLE t1; +include/save_master_gtid.inc +connection slave; +include/sync_with_master_gtid.inc +connection master; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_parallel_seq.result b/mysql-test/suite/rpl/r/rpl_parallel_seq.result index 8f55f52e54c..02287d54e33 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_seq.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_seq.result @@ -127,4 +127,14 @@ CREATE SEQUENCE s4; DROP SEQUENCE s2,s3,s4; DROP TABLE ti; connection slave; +connection master; +CREATE SEQUENCE s; +SELECT NEXTVAL(s); +NEXTVAL(s) +1 +flush binary logs; +DROP SEQUENCE s; +DROP SEQUENCE s; +connection slave; +connection master; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_parallel_slave_bgc_kill.result b/mysql-test/suite/rpl/r/rpl_parallel_slave_bgc_kill.result index ba131ea094f..6b75dbf6181 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_slave_bgc_kill.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_slave_bgc_kill.result @@ -206,10 +206,12 @@ RETURN x; END || SET sql_log_bin=1; +include/stop_slave_io.inc connection server_1; INSERT INTO t3 VALUES (49,0); connection server_2; -START SLAVE SQL_THREAD; +CHANGE MASTER TO master_use_gtid=no; +include/start_slave.inc SELECT * FROM t3 WHERE a >= 40 ORDER BY a; a b 41 41 @@ -239,10 +241,6 @@ SET GLOBAL slave_parallel_threads=0; SET GLOBAL slave_parallel_threads=10; include/start_slave.inc *** 3. Same as (2), but not using gtid mode *** -connection server_2; -include/stop_slave.inc -CHANGE MASTER TO master_use_gtid=no; -include/start_slave.inc connection server_1; connection con_temp3; SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1'; diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_fail_over.result b/mysql-test/suite/rpl/r/rpl_semi_sync_fail_over.result index ca7c802bfbe..49fdb485c50 100644 --- a/mysql-test/suite/rpl/r/rpl_semi_sync_fail_over.result +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_fail_over.result @@ -44,7 +44,9 @@ SET DEBUG_SYNC= "now WAIT_FOR con1_ready"; connection server_2; include/wait_for_slave_param.inc [Slave_SQL_Running_State] include/stop_slave.inc -include/assert.inc [Table t1 should have 2 rows.] +select count(*) 'on slave must be 2' from t1; +on slave must be 2 +2 SELECT @@GLOBAL.gtid_current_pos; @@GLOBAL.gtid_current_pos 0-1-4 @@ -52,7 +54,9 @@ SELECT @@GLOBAL.gtid_current_pos; connection server_1; # Ensuring variable rpl_semi_sync_slave_enabled is ON.. # Ensuring status rpl_semi_sync_slave_status is OFF.. -include/assert.inc [Table t1 should have 1 rows.] +select count(*) 'on master must be 1' from t1; +on master must be 1 +1 FOUND 1 /truncated binlog file:.*master.*000001/ in mysqld.1.err disconnect conn_client; connection server_2; @@ -79,9 +83,9 @@ SHOW VARIABLES LIKE 'gtid_slave_pos'; Variable_name Value gtid_slave_pos 0-1-4 connection server_1; -SELECT COUNT(*) = 3 as 'true' FROM t1; -true -1 +SELECT COUNT(*) 'must be 3' FROM t1; +must be 3 +3 # ... the gtid states on the slave: SHOW VARIABLES LIKE 'gtid_slave_pos'; Variable_name Value @@ -113,18 +117,22 @@ connection server_2; #================================================================= connect conn_client,127.0.0.1,root,,test,$SERVER_MYPORT_2,; SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL con1_ready WAIT_FOR con1_go"; +SET DEBUG_SYNC= "commit_after_release_LOCK_after_binlog_sync WAIT_FOR con1_go1"; SET STATEMENT server_id=1 FOR INSERT INTO t1 VALUES (4, REPEAT("x", 4100)); connect conn_client_2,127.0.0.1,root,,test,$SERVER_MYPORT_2,; SET DEBUG_SYNC= "now WAIT_FOR con1_ready"; -SET GLOBAL debug_dbug="d,Notify_binlog_EOF"; +SET DEBUG_SYNC= "commit_before_get_LOCK_after_binlog_sync SIGNAL con1_go"; +SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL con2_ready"; INSERT INTO t1 VALUES (5, REPEAT("x", 4100)); connection server_2; -SET DEBUG_SYNC= "now WAIT_FOR eof_reached"; +SET DEBUG_SYNC= "now WAIT_FOR con2_ready"; # Kill the server connection server_1; include/wait_for_slave_param.inc [Slave_SQL_Running_State] include/stop_slave.inc -include/assert.inc [Table t1 should have 5 rows.] +select count(*) 'on slave must be 5' from t1; +on slave must be 5 +5 SELECT @@GLOBAL.gtid_current_pos; @@GLOBAL.gtid_current_pos 0-2-7 @@ -132,7 +140,9 @@ SELECT @@GLOBAL.gtid_current_pos; connection server_2; # Ensuring variable rpl_semi_sync_slave_enabled is ON.. # Ensuring status rpl_semi_sync_slave_status is OFF.. -include/assert.inc [Table t1 should have 3 rows.] +select count(*) 'on master must be 3' from t1; +on master must be 3 +3 FOUND 1 /truncated binlog file:.*slave.*000002.* to remove transactions starting from GTID 0-1-6/ in mysqld.2.err disconnect conn_client; connection server_1; @@ -159,9 +169,9 @@ SHOW VARIABLES LIKE 'gtid_slave_pos'; Variable_name Value gtid_slave_pos 0-2-7 connection server_2; -SELECT COUNT(*) = 6 as 'true' FROM t1; -true -1 +SELECT COUNT(*) 'must be 6 as' FROM t1; +must be 6 as +6 # ... the gtid states on the slave: SHOW VARIABLES LIKE 'gtid_slave_pos'; Variable_name Value @@ -205,7 +215,9 @@ SET DEBUG_SYNC= "now WAIT_FOR con3_ready"; connection server_2; include/wait_for_slave_param.inc [Slave_SQL_Running_State] include/stop_slave.inc -include/assert.inc [Table t1 should have 7 rows.] +select count(*) 'on slave must be 7' from t1; +on slave must be 7 +7 SELECT @@GLOBAL.gtid_current_pos; @@GLOBAL.gtid_current_pos 0-1-9 @@ -213,7 +225,9 @@ SELECT @@GLOBAL.gtid_current_pos; connection server_1; # Ensuring variable rpl_semi_sync_slave_enabled is ON.. # Ensuring status rpl_semi_sync_slave_status is OFF.. -include/assert.inc [Table t1 should have 6 rows.] +select count(*) 'on master must be 6' from t1; +on master must be 6 +6 FOUND 1 /truncated binlog file:.*master.*000002.* to remove transactions starting from GTID 0-1-9/ in mysqld.1.err disconnect conn_client; connection server_2; @@ -242,9 +256,9 @@ Variable_name Value gtid_slave_pos 0-1-9 connection server_1; include/sync_with_master_gtid.inc -SELECT COUNT(*) = 8 as 'true' FROM t1; -true -1 +SELECT COUNT(*) 'must be 8' FROM t1; +must be 8 +8 # ... the gtid states on the slave: SHOW VARIABLES LIKE 'gtid_slave_pos'; Variable_name Value diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_master_shutdown.result b/mysql-test/suite/rpl/r/rpl_semi_sync_master_shutdown.result index 6124ba01679..8803b4c3392 100644 --- a/mysql-test/suite/rpl/r/rpl_semi_sync_master_shutdown.result +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_master_shutdown.result @@ -4,7 +4,7 @@ connection master; SET @@GLOBAL.rpl_semi_sync_master_enabled = 1; connection slave; include/stop_slave.inc -SET @@GLOBAL. rpl_semi_sync_slave_enabled = 1; +SET @@GLOBAL.rpl_semi_sync_slave_enabled = 1; include/start_slave.inc connection master; CREATE TABLE t1 (a INT); @@ -21,7 +21,6 @@ connection slave; include/wait_for_slave_sql_to_start.inc include/wait_for_slave_io_to_start.inc connection master; -SET @@GLOBAL.debug_dbug=""; SET @@GLOBAL. rpl_semi_sync_master_enabled = 0; connection master; DROP TABLE t1; 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 a8e158a25e4..3048b6b5635 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 @@ -505,8 +505,8 @@ disconnect con1; connection default; connection con2; SHUTDOWN WAIT FOR ALL SLAVES; -connection server_2; -include/assert_grep.inc [Ensure the primary waited for the ACK of the killed thread] +# Ensure the primary waited for the ACK of the killed thread +FOUND 5 /Delaying shutdown to await semi-sync ACK/ in mysqld.1.err connection default; connection server_1; connection server_2; diff --git a/mysql-test/suite/rpl/r/rpl_shutdown_sighup.result b/mysql-test/suite/rpl/r/rpl_shutdown_sighup.result new file mode 100644 index 00000000000..01b35f1dc58 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_shutdown_sighup.result @@ -0,0 +1,50 @@ +include/master-slave.inc +[connection master] +connection slave; +set statement sql_log_bin=0 for call mtr.add_suppression("Signal handler thread did not exit in a timely manner"); +# +# Main test +connection master; +create table t1 (a int); +insert into t1 values (1); +include/save_master_gtid.inc +connection slave; +include/sync_with_master_gtid.inc +set @@global.debug_dbug= "+d,hold_sighup_log_refresh"; +# Waiting for sighup to reach reload_acl_and_cache.. +set debug_sync="now wait_for in_reload_acl_and_cache"; +# Signalling signal handler to proceed to sleep before REFRESH_HOSTS +set debug_sync="now signal refresh_logs"; +# Starting shutdown (note this will take 3+ seconds due to DBUG my_sleep in reload_acl_and_cache) +shutdown; +connection server_2; +connection slave; +include/assert_grep.inc [Ensure Mariadbd did not segfault when shutting down] +connection master; +connection slave; +# +# Error testcase to ensure an error message is shown if the signal +# takes longer than the timeout while processing the SIGHUP +connection slave; +set @@global.debug_dbug= "+d,force_sighup_processing_timeout"; +set @@global.debug_dbug= "+d,hold_sighup_log_refresh"; +connection master; +insert into t1 values (1); +include/save_master_gtid.inc +connection slave; +include/sync_with_master_gtid.inc +# Waiting for sighup to reach reload_acl_and_cache.. +set debug_sync="now wait_for in_reload_acl_and_cache"; +# Signalling signal handler to proceed to sleep before REFRESH_HOSTS +set debug_sync="now signal refresh_logs"; +# Starting shutdown (note this will take 3+ seconds due to DBUG my_sleep in reload_acl_and_cache) +shutdown; +connection server_2; +connection slave; +include/assert_grep.inc [Ensure warning is issued that signal handler thread is still processing] +# +# Cleanup +connection master; +drop table t1; +include/rpl_end.inc +# End of rpl_shutdown_sighup.test diff --git a/mysql-test/suite/rpl/r/rpl_skip_error.result b/mysql-test/suite/rpl/r/rpl_skip_error.result index eb6324ff987..03fc8a7836f 100644 --- a/mysql-test/suite/rpl/r/rpl_skip_error.result +++ b/mysql-test/suite/rpl/r/rpl_skip_error.result @@ -122,6 +122,31 @@ connection slave; # Slave_skipped_errros = 5 **** We cannot execute a select as there are differences in the **** behavior between STMT and RBR. +**** +**** Ensure transactions which are skipped due to encountering a +**** non-deadlock error which is present in --slave-skip-errors result +**** in partially committed transactions +connection master; +CREATE TABLE t3 (a INT UNIQUE) ENGINE=InnoDB; +connection slave; +connection slave; +INSERT INTO t3 VALUES (3); +connection master; +BEGIN; +INSERT INTO t3 VALUES (1); +INSERT INTO t3 VALUES (2); +INSERT INTO t3 VALUES (3); +INSERT INTO t3 VALUES (4); +COMMIT; +connection slave; +**** Master and slave tables should have the same data, due to the +**** partially replicated transaction's data overlapping with the data +**** that pre-existed on the slave. That is, despite the transaction +**** consisting of 4 statements, the errored statement should be ignored +**** and the other 3 should commit successfully. +include/diff_tables.inc [master:t3,slave:t3] +connection master; +DROP TABLE t3; ==== Clean Up ==== connection master; DROP TABLE t1; diff --git a/mysql-test/suite/rpl/r/rpl_temporary_error2_skip_all.result b/mysql-test/suite/rpl/r/rpl_temporary_error2_skip_all.result new file mode 100644 index 00000000000..9819aafa5cf --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_temporary_error2_skip_all.result @@ -0,0 +1,64 @@ +include/master-slave.inc +[connection master] +call mtr.add_suppression("Deadlock found when trying to get lock; try restarting transaction"); +*** Provoke a deadlock on the slave, check that transaction retry succeeds. *** +connection master; +CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t1(a) VALUES (1), (2), (3), (4), (5); +connection slave; +SELECT * FROM t1 ORDER BY a; +a b +1 NULL +2 NULL +3 NULL +4 NULL +5 NULL +SET sql_log_bin=0; +ALTER TABLE t2 ENGINE=MyISAM; +SET sql_log_bin=1; +connect con_temp1,127.0.0.1,root,,test,$SERVER_MYPORT_2,; +connection con_temp1; +BEGIN; +UPDATE t1 SET b=2 WHERE a=4; +INSERT INTO t2 VALUES (2); +DELETE FROM t2 WHERE a=2; +connection master; +BEGIN; +UPDATE t1 SET b=1 WHERE a=2; +INSERT INTO t2 VALUES (1); +UPDATE t1 SET b=1 WHERE a=4; +COMMIT; +connection slave; +connection con_temp1; +UPDATE t1 SET b=2 WHERE a=2; +SELECT * FROM t1 WHERE a<10 ORDER BY a; +a b +1 NULL +2 2 +3 NULL +4 2 +5 NULL +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +connection slave; +SELECT * FROM t1 ORDER BY a; +a b +1 NULL +2 NULL +3 NULL +4 NULL +5 NULL +* There will be one row in t2 because the ignored deadlock does not retry. +SELECT * FROM t2 ORDER BY a; +a +1 +retries +0 +Last_SQL_Errno = '0' +Last_SQL_Error = '' +connection master; +DROP TABLE t1; +DROP TABLE t2; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/parallel_backup_xa.inc b/mysql-test/suite/rpl/t/parallel_backup_xa.inc index 83a6fb79345..5f287aa0ca6 100644 --- a/mysql-test/suite/rpl/t/parallel_backup_xa.inc +++ b/mysql-test/suite/rpl/t/parallel_backup_xa.inc @@ -41,7 +41,7 @@ if ($slave_ooo_error) { SET @sav_innodb_lock_wait_timeout = @@global.innodb_lock_wait_timeout; SET @sav_slave_transaction_retries = @@global.slave_transaction_retries; - SET @@global.innodb_lock_wait_timeout =1; + SET @@global.innodb_lock_wait_timeout =5; SET @@global.slave_transaction_retries=0; } --source include/start_slave.inc diff --git a/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test b/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test index 2ce273860fe..19074ce9a84 100644 --- a/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test +++ b/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test @@ -42,7 +42,7 @@ insert into ti set a=null; insert into tm set a=null; set @@global.debug_dbug="+d,crash_before_send_xid"; ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.1.expect connection slave; let $do_domain_ids_before= query_get_value(SHOW SLAVE STATUS, Replicate_Do_Domain_Ids, 1); @@ -64,7 +64,7 @@ connection master; --enable_reconnect --let $rpl_server_number=1 --source include/rpl_start_server.inc -#--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +#--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --source include/wait_until_connected_again.inc --echo # Master has restarted successfully save_master_pos; diff --git a/mysql-test/suite/rpl/t/rpl_domain_id_filter_restart.test b/mysql-test/suite/rpl/t/rpl_domain_id_filter_restart.test index 8083b8f232f..38cbbdec7f3 100644 --- a/mysql-test/suite/rpl/t/rpl_domain_id_filter_restart.test +++ b/mysql-test/suite/rpl/t/rpl_domain_id_filter_restart.test @@ -35,9 +35,10 @@ SET @@session.gtid_domain_id= 1; INSERT INTO t2 VALUES(1); SELECT * FROM t2; -sync_slave_with_master; +source include/save_master_gtid.inc; connection slave; +source include/sync_with_master_gtid.inc; SELECT * FROM t1; SELECT * FROM t2; diff --git a/mysql-test/suite/rpl/t/rpl_gtid_crash-slave.opt b/mysql-test/suite/rpl/t/rpl_gtid_crash-slave.opt index 69c1a64e388..5b3fb44c910 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_crash-slave.opt +++ b/mysql-test/suite/rpl/t/rpl_gtid_crash-slave.opt @@ -1 +1 @@ ---master-retry-count=100 +--master-retry-count=100 --slave-net-timeout=10 diff --git a/mysql-test/suite/rpl/t/rpl_gtid_header_valid.test b/mysql-test/suite/rpl/t/rpl_gtid_header_valid.test new file mode 100644 index 00000000000..db546787914 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_gtid_header_valid.test @@ -0,0 +1,181 @@ +# +# This test ensures that, when a GTID event is constructed by reading its +# content from a binlog file, the reader (e.g. replica, in this test) cannot +# read beyond the length of the GTID event. That is, we ensure that the +# structure indicated by its flags and extra_flags are consistent with the +# actual content of the event. +# +# To spoof a broken GTID log event, we use the DEBUG_DBUG mechanism to inject +# the master to write invalid GTID events for each flag. The transaction is +# given a commit id to ensure the event is not shorter than GTID_HEADER_LEN, +# which would result in zero padding up to GTID_HEADER_LEN. +# +# +# References: +# MDEV-33672: Gtid_log_event Construction from File Should Ensure Event +# Length When Using Extra Flags +# + +--source include/have_debug.inc + +# GTID event extra_flags are format independent +--source include/have_binlog_format_row.inc +--source include/have_innodb.inc +--source include/master-slave.inc + +--echo # +--echo # Initialize test data +--connection master +create table t1 (a int) engine=innodb; +--source include/save_master_gtid.inc +set @@SESSION.debug_dbug= "+d,binlog_force_commit_id"; + +--connection slave +set SQL_LOG_BIN= 0; +call mtr.add_suppression('Found invalid event in binary log'); +call mtr.add_suppression('Slave SQL.*Relay log read failure: Could not parse relay log event entry.* 1594'); +set SQL_LOG_BIN= 1; +--source include/sync_with_master_gtid.inc +--source include/stop_slave.inc +--source include/start_slave.inc +--let $cid_ctr= 100 + + +--echo # +--echo # Test FL_PREPARED_XA +--connection master +set @@SESSION.debug_dbug= "+d,negate_xid_from_gtid"; +--eval set @commit_id= $cid_ctr + +XA START 'x1'; +insert into t1 values (1); +XA END 'x1'; +XA PREPARE 'x1'; +set @@SESSION.debug_dbug= "-d,negate_xid_from_gtid"; +XA COMMIT 'x1'; +--source include/save_master_gtid.inc + +--echo # Waiting for slave to find invalid event.. +--connection slave +let $slave_sql_errno= 1594; # ER_SLAVE_RELAY_LOG_READ_FAILURE +source include/wait_for_slave_sql_error.inc; +STOP SLAVE IO_THREAD; + +--echo # Reset master binlogs (as there is an invalid event) and slave state +--connection master +RESET MASTER; +--connection slave +RESET MASTER; +RESET SLAVE; +set @@global.gtid_slave_pos=""; +--source include/start_slave.inc + + +--echo # +--echo # Test FL_COMPLETED_XA +--connection master +--inc $cid_ctr +--eval set @commit_id= $cid_ctr +XA START 'x1'; +--let $next_val = `SELECT max(a)+1 FROM t1` +--eval insert into t1 values ($next_val) +XA END 'x1'; +XA PREPARE 'x1'; +set @@SESSION.debug_dbug= "+d,negate_xid_from_gtid"; +XA COMMIT 'x1'; +set @@SESSION.debug_dbug= "-d,negate_xid_from_gtid"; +--source include/save_master_gtid.inc + +--echo # Waiting for slave to find invalid event.. +--connection slave +let $slave_sql_errno= 1594; # ER_SLAVE_RELAY_LOG_READ_FAILURE +source include/wait_for_slave_sql_error.inc; +STOP SLAVE IO_THREAD; + +--echo # Cleanup hanging XA PREPARE on slave +set statement SQL_LOG_BIN=0 for XA COMMIT 'x1'; + +--echo # Reset master binlogs (as there is an invalid event) and slave state +--connection master +RESET MASTER; +--connection slave +RESET MASTER; +RESET SLAVE; +set @@global.gtid_slave_pos=""; +--source include/start_slave.inc + + +--echo # +--echo # Test Missing xid.data (but has format id and length description parts) + +--connection master +--eval set @commit_id= $cid_ctr + +XA START 'x1'; +insert into t1 values (1); +XA END 'x1'; +XA PREPARE 'x1'; +set @@SESSION.debug_dbug= "+d,negate_xid_data_from_gtid"; +XA COMMIT 'x1'; +set @@SESSION.debug_dbug= "-d,negate_xid_data_from_gtid"; +--source include/save_master_gtid.inc + +--echo # Waiting for slave to find invalid event.. +--connection slave +let $slave_sql_errno= 1594; # ER_SLAVE_RELAY_LOG_READ_FAILURE +source include/wait_for_slave_sql_error.inc; +STOP SLAVE IO_THREAD; + +--echo # Cleanup hanging XA PREPARE on slave +set statement SQL_LOG_BIN=0 for XA COMMIT 'x1'; + +--echo # Reset master binlogs (as there is an invalid event) and slave state +--connection master +RESET MASTER; +--connection slave +RESET MASTER; +RESET SLAVE; +set @@global.gtid_slave_pos=""; +--source include/start_slave.inc + + +--echo # +--echo # Test FL_EXTRA_MULTI_ENGINE +--connection master +set @old_dbug= @@SESSION.debug_dbug; +set @@SESSION.debug_dbug= "+d,inject_fl_extra_multi_engine_into_gtid"; +--inc $cid_ctr +--eval set @commit_id= $cid_ctr +--let $next_val = `SELECT max(a)+1 FROM t1` +--eval insert into t1 values ($next_val) +--source include/save_master_gtid.inc +set @@SESSION.debug_dbug=@old_dbug; + +--connection slave +--echo # Waiting for slave to find invalid event.. +let $slave_sql_errno= 1594; # ER_SLAVE_RELAY_LOG_READ_FAILURE +source include/wait_for_slave_sql_error.inc; +STOP SLAVE IO_THREAD; + +--echo # Reset master binlogs (as there is an invalid event) and slave state +--connection master +RESET MASTER; + +--connection slave +RESET SLAVE; +RESET MASTER; +set @@global.gtid_slave_pos=""; +--source include/start_slave.inc + +--echo # +--echo # Cleanup + +--connection master +drop table t1; +--source include/save_master_gtid.inc + +--connection slave +--source include/sync_with_master_gtid.inc + +--source include/rpl_end.inc +--echo # End of rpl_gtid_header_valid.test diff --git a/mysql-test/suite/rpl/t/rpl_mysql_manager_race_condition.test b/mysql-test/suite/rpl/t/rpl_mysql_manager_race_condition.test index 751da3158b7..dd4a0fbbc99 100644 --- a/mysql-test/suite/rpl/t/rpl_mysql_manager_race_condition.test +++ b/mysql-test/suite/rpl/t/rpl_mysql_manager_race_condition.test @@ -18,8 +18,14 @@ # associated with this test should enforce that the binlog background thread is # not created before the handle manager is initialized. # +# Addendum 1) This test is extended for MDEV-33799, as the original fix +# left out the possibility that the binlog background thread can be +# started during recovery if the binary log is used as the transaction +# coordinator. This resulted in similar segfaults as seen by MDEV-26473. +# # References: # MDEV-26473 mysqld got exception 0xc0000005 (rpl_slave_state/rpl_load_gtid_slave_state) +# MDEV-33799 mysql_manager_submit Segfault at Startup Still Possible During Recovery # --source include/have_debug.inc @@ -53,6 +59,63 @@ create table t1 (a int); --source include/start_slave.inc +--echo # +--echo # MDEV-33799 +--echo # Ensure that when the binary log is used for recovery (as tc log), that +--echo # the recovery process cannot start the binlog background thread before +--echo # the mysql handle manager has started. +--connection slave + +--echo # Add test suppresssions so crash recovery messages don't fail the test +set session sql_log_bin=0; +call mtr.add_suppression("mariadbd: Got error '145.*"); +call mtr.add_suppression("Checking table:.*"); +call mtr.add_suppression("mysql.gtid_slave_pos:.*hasn't closed the table properly"); +call mtr.add_suppression("Can't init tc log"); +call mtr.add_suppression("Aborting"); +set session sql_log_bin=1; + +--echo # Create slave-side only table +create table t2 (a int) engine=innodb; + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF + +--echo # Crash mariadbd when binlogging transaction to corrupt database state +--connection slave1 +set @@session.debug_dbug="+d,crash_before_writing_xid"; +--send insert into t2 values (1) + +--connection slave +--source include/wait_until_disconnected.inc + +--connection slave1 +--error 2013,ER_CONNECTION_KILLED +--reap + +--echo # Restart mariadbd in recovery mode. Note --tc-heuristic-recover +--echo # forces mysqld to exit with error, so we run mariadbd via CLI +--echo # MYSQLD_LAST_CMD --debug_dbug="+d,delay_start_handle_manager" --tc-heuristic-recover=COMMIT +--error 1 +--exec $MYSQLD_LAST_CMD --debug_dbug="+d,delay_start_handle_manager" --tc-heuristic-recover=COMMIT + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart +EOF + +--connection server_2 +--enable_reconnect +--source include/wait_until_connected_again.inc +--connection slave1 +--enable_reconnect +--source include/wait_until_connected_again.inc +--connection slave +--enable_reconnect +--source include/wait_until_connected_again.inc +--source include/start_slave.inc + + --echo # --echo # Cleanup --echo # @@ -63,5 +126,6 @@ drop table t1; --connection slave --source include/sync_with_master_gtid.inc +drop table t2; --source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_multi_domain_xa.test b/mysql-test/suite/rpl/t/rpl_parallel_multi_domain_xa.test new file mode 100644 index 00000000000..da1aaea130f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_multi_domain_xa.test @@ -0,0 +1,173 @@ +# Similar to rpl_parallel_optimistic_xa to verify XA +# parallel execution with multiple gtid domain. +# References: +# MDEV-33668 Adapt parallel slave's round-robin scheduling to XA events + +--source include/have_innodb.inc +--source include/have_perfschema.inc +--source include/master-slave.inc + +# Tests' global declarations +--let $trx = _trx_ + +call mtr.add_suppression("Deadlock found when trying to get lock; try restarting transaction"); +call mtr.add_suppression("WSREP: handlerton rollback failed"); + +--connection master +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +--save_master_pos + +# Prepare to restart slave into optimistic parallel mode +--connection slave +--sync_with_master +--source include/stop_slave.inc +SET @old_parallel_threads = @@GLOBAL.slave_parallel_threads; +SET @old_slave_domain_parallel_threads = @@GLOBAL.slave_domain_parallel_threads; +SET @@global.slave_parallel_threads = 5; +SET @@global.slave_domain_parallel_threads = 3; +SET @old_parallel_mode = @@GLOBAL.slave_parallel_mode; + +CHANGE MASTER TO master_use_gtid=slave_pos; + +--connection master +CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 0); +--source include/save_master_gtid.inc + +--connection slave +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +--source include/stop_slave.inc + +--let $mode = 2 +# mode = 2 is optimistic +SET @@global.slave_parallel_mode ='optimistic'; +while ($mode) +{ + --connection master + # + # create XA events alternating gtid domains to run them in parallel on slave. + # + --let $domain_num = 3 + --let $trx_num = 777 + --let $i = $trx_num + --let $conn = master + --disable_query_log + while($i > 0) + { + --let $domain_id = `SELECT $i % $domain_num` + --eval set @@gtid_domain_id = $domain_id + # 'decision' to commit 0, or rollback 1 + --let $decision = `SELECT $i % 2` + --eval XA START '$conn$trx$i' + --eval UPDATE t1 SET b = 1 - 2 * $decision WHERE a = 1 + --eval XA END '$conn$trx$i' + --eval XA PREPARE '$conn$trx$i' + --let $term = COMMIT + if ($decision) + { + --let $term = ROLLBACK + } + --eval XA $term '$conn$trx$i' + + --dec $i + } + --enable_query_log + --source include/save_master_gtid.inc + + --connection slave + if (`select $mode = 1`) + { + SET @@global.slave_parallel_mode ='conservative'; + } + --source include/start_slave.inc + --source include/sync_with_master_gtid.inc + --source include/stop_slave.inc + + --dec $mode +} + + +# Generations test. +# Create few ranges of XAP groups length of greater than +# 3 * slave_parallel_threads + 1 +# terminated upon each range. +--let $iter = 3 +--let $generation_len = @@global.slave_parallel_threads +--let $domain_num = 3 +--disable_query_log +--connection master +while ($iter) +{ + --let $k = `select 3 * 3 * $generation_len` + --let $_k = $k + while ($k) + { + --source include/count_sessions.inc + --connect(con$k,localhost,root,,) + # + # create XA events alternating gtid domains to run them in parallel on slave. + # + --let $domain_id = `SELECT $k % $domain_num` + --eval set @@gtid_domain_id = $domain_id + --eval XA START '$trx$k' + --eval INSERT INTO t1 VALUES ($k + 1, $iter) + --eval XA END '$trx$k' + --eval XA PREPARE '$trx$k' + + --disconnect con$k + --connection master + --source include/wait_until_count_sessions.inc + + --dec $k + } + + --connection master + --let $k = $_k + while ($k) + { + --let $term = COMMIT + --let $decision = `SELECT $k % 2` + if ($decision) + { + --let $term = ROLLBACK + } + --eval XA $term '$trx$k' + } + --dec $iter +} +--enable_query_log +--source include/save_master_gtid.inc + +--connection slave +SET @@global.slave_parallel_mode = 'optimistic'; +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc + + +# +# Overall consistency check +# +--let $diff_tables= master:t1, slave:t1 +--source include/diff_tables.inc + + +# +# Clean up. +# +--connection slave +--source include/stop_slave.inc +SET @@global.slave_parallel_mode = @old_parallel_mode; +SET @@global.slave_parallel_threads = @old_parallel_threads; +SET @@global.slave_domain_parallel_threads = @old_slave_domain_parallel_threads; +--source include/start_slave.inc + +--connection master +DROP TABLE t1; +--source include/save_master_gtid.inc + +--connection slave +--source include/sync_with_master_gtid.inc + +--connection master +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_seq.test b/mysql-test/suite/rpl/t/rpl_parallel_seq.test index b1b15412b16..cc361a7b35b 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_seq.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_seq.test @@ -195,4 +195,22 @@ DROP TABLE ti; --sync_slave_with_master +# MDEV-31779 server crash in Rows_log_event::update_sequence at replaying binlog +--connection master +--let $binlog_file = query_get_value(SHOW MASTER STATUS, File, 1) +--let $binlog_start = query_get_value(SHOW MASTER STATUS, Position, 1) +CREATE SEQUENCE s; +--disable_ps2_protocol +SELECT NEXTVAL(s); +--enable_ps2_protocol +flush binary logs; +DROP SEQUENCE s; +--exec $MYSQL_BINLOG $datadir/$binlog_file | $MYSQL test +DROP SEQUENCE s; + +--sync_slave_with_master + +--connection master + + --source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_slave_bgc_kill.test b/mysql-test/suite/rpl/t/rpl_parallel_slave_bgc_kill.test index efb998b0443..94f19a6cdd7 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_slave_bgc_kill.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_slave_bgc_kill.test @@ -295,13 +295,14 @@ CREATE FUNCTION foo(x INT, d1 VARCHAR(500), d2 VARCHAR(500)) || --delimiter ; SET sql_log_bin=1; - +--source include/stop_slave_io.inc --connection server_1 INSERT INTO t3 VALUES (49,0); --save_master_pos --connection server_2 -START SLAVE SQL_THREAD; +CHANGE MASTER TO master_use_gtid=no; +--source include/start_slave.inc --sync_with_master SELECT * FROM t3 WHERE a >= 40 ORDER BY a; # Restore the foo() function. @@ -334,11 +335,6 @@ SET GLOBAL slave_parallel_threads=10; --echo *** 3. Same as (2), but not using gtid mode *** ---connection server_2 ---source include/stop_slave.inc -CHANGE MASTER TO master_use_gtid=no; ---source include/start_slave.inc - --connection server_1 # Set up three transactions on the master that will be group-committed # together so they can be replicated in parallel on the slave. diff --git a/mysql-test/suite/rpl/t/rpl_relay_max_extension.test b/mysql-test/suite/rpl/t/rpl_relay_max_extension.test index acca2f6954c..b6a8ccb545c 100644 --- a/mysql-test/suite/rpl/t/rpl_relay_max_extension.test +++ b/mysql-test/suite/rpl/t/rpl_relay_max_extension.test @@ -47,7 +47,7 @@ RESET SLAVE; --echo # --let $datadir = `select @@datadir` ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +--write_line wait $MYSQLTEST_VARDIR/tmp/mysqld.2.expect --shutdown_server 10 --source include/wait_until_disconnected.inc @@ -64,7 +64,7 @@ RESET SLAVE; --echo # Restart slave server --echo # ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.2.expect --enable_reconnect --source include/wait_until_connected_again.inc SET @save_slave_parallel_threads= @@GLOBAL.slave_parallel_threads; diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_crash.inc b/mysql-test/suite/rpl/t/rpl_semi_sync_crash.inc index b092d0018b0..bb705d390ac 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_crash.inc +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_crash.inc @@ -34,14 +34,16 @@ if ($case == 1) if ($case == 2) { SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL con1_ready WAIT_FOR con1_go"; + SET DEBUG_SYNC= "commit_after_release_LOCK_after_binlog_sync WAIT_FOR con1_go1"; --send_eval $query_to_crash --connect (conn_client_2,127.0.0.1,root,,test,$SERVER_MYPORT_2,) # use the same signal with $query_to_crash SET DEBUG_SYNC= "now WAIT_FOR con1_ready"; - SET GLOBAL debug_dbug="d,Notify_binlog_EOF"; + SET DEBUG_SYNC= "commit_before_get_LOCK_after_binlog_sync SIGNAL con1_go"; + SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL con2_ready"; --send_eval $query2_to_crash --connection server_$server_to_crash - SET DEBUG_SYNC= "now WAIT_FOR eof_reached"; + SET DEBUG_SYNC= "now WAIT_FOR con2_ready"; --source include/kill_mysqld.inc } @@ -68,9 +70,7 @@ source include/wait_for_slave_param.inc; --error 2003 --source include/stop_slave.inc ---let $assert_cond= COUNT(*) = $expected_rows_on_slave FROM t1 ---let $assert_text= Table t1 should have $expected_rows_on_slave rows. ---source include/assert.inc +--eval select count(*) 'on slave must be $expected_rows_on_slave' from t1 SELECT @@GLOBAL.gtid_current_pos; @@ -95,9 +95,7 @@ if (`SELECT strcmp("OFF", "$slave_semi_sync_status") != 0`) --die Slave started with skip-slave-start yet started with rpl_semi_sync_slave_status=ON } ---let $assert_cond= COUNT(*) = $expected_rows_on_master FROM t1 ---let $assert_text= Table t1 should have $expected_rows_on_master rows. ---source include/assert.inc +--eval select count(*) 'on master must be $expected_rows_on_master' from t1 # Check error log for correct messages. let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.$server_to_crash.err; diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.test b/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.test index e1e7a4f1de3..e4d0bc0acd1 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.test +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.test @@ -83,7 +83,7 @@ SHOW VARIABLES LIKE 'gtid_slave_pos'; --connection server_1 --sync_with_master ---eval SELECT COUNT(*) = $rows_so_far as 'true' FROM t1 +--eval SELECT COUNT(*) 'must be $rows_so_far' FROM t1 --echo # ... the gtid states on the slave: SHOW VARIABLES LIKE 'gtid_slave_pos'; SHOW VARIABLES LIKE 'gtid_binlog_pos'; @@ -134,7 +134,7 @@ SHOW VARIABLES LIKE 'gtid_slave_pos'; --connection server_2 --sync_with_master ---eval SELECT COUNT(*) = $rows_so_far as 'true' FROM t1 +--eval SELECT COUNT(*) 'must be $rows_so_far as' FROM t1 --echo # ... the gtid states on the slave: SHOW VARIABLES LIKE 'gtid_slave_pos'; SHOW VARIABLES LIKE 'gtid_binlog_pos'; @@ -185,7 +185,7 @@ SHOW VARIABLES LIKE 'gtid_slave_pos'; --connection server_1 --source include/sync_with_master_gtid.inc ---eval SELECT COUNT(*) = $rows_so_far as 'true' FROM t1 +--eval SELECT COUNT(*) 'must be $rows_so_far' FROM t1 --echo # ... the gtid states on the slave: SHOW VARIABLES LIKE 'gtid_slave_pos'; SHOW VARIABLES LIKE 'gtid_binlog_pos'; diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test b/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test index 05e6fcca143..d653d84c3b4 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_master_shutdown.test @@ -4,19 +4,17 @@ # finishes off as specified in particular trying to connect even to a shut down # master for a semisync firewell routine. -source include/not_embedded.inc; -source include/have_debug.inc; source include/master-slave.inc; --connection master ---let $sav_enabled_master=`SELECT @@GLOBAL.rpl_semi_sync_master_enabled ` +--let $sav_enabled_master=`SELECT @@GLOBAL.rpl_semi_sync_master_enabled` SET @@GLOBAL.rpl_semi_sync_master_enabled = 1; --connection slave source include/stop_slave.inc; ---let $sav_enabled_slave=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled ` -SET @@GLOBAL. rpl_semi_sync_slave_enabled = 1; +--let $sav_enabled_slave=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled` +SET @@GLOBAL.rpl_semi_sync_slave_enabled = 1; source include/start_slave.inc; --connection master @@ -52,7 +50,6 @@ source include/rpl_start_server.inc; #--source include/start_slave.inc --connection master -SET @@GLOBAL.debug_dbug=""; --eval SET @@GLOBAL. rpl_semi_sync_master_enabled = $sav_enabled_master --connection master 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 c321f2bf72f..4ed9ca0aa7c 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 @@ -206,7 +206,6 @@ SET GLOBAL debug_dbug="+d,simulate_delay_semisync_slave_reply"; --echo # Wait for thd to begin semi-sync wait.. --let $wait_condition= SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE state = 'Waiting for semi-sync ACK from slave' --source include/wait_condition.inc ---source include/wait_condition.inc --echo # ..done --disconnect con1 @@ -220,15 +219,10 @@ EOF SHUTDOWN WAIT FOR ALL SLAVES; --source include/wait_until_disconnected.inc -# Run assert_grep on server_2 as it uses SQL commands for verification, but -# server_1 has gone away ---connection server_2 ---let $assert_text= Ensure the primary waited for the ACK of the killed thread ---let $assert_select= Delaying shutdown to await semi-sync ACK ---let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err ---let $assert_count= 5 ---let $assert_only_after=CURRENT_TEST ---source include/assert_grep.inc +--echo # Ensure the primary waited for the ACK of the killed thread +--let $SEARCH_PATTERN= Delaying shutdown to await semi-sync ACK +--let $SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err +--source include/search_pattern_in_file.inc --connection default --source include/wait_until_disconnected.inc diff --git a/mysql-test/suite/rpl/t/rpl_shutdown_sighup.test b/mysql-test/suite/rpl/t/rpl_shutdown_sighup.test new file mode 100644 index 00000000000..d1940f81a85 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_shutdown_sighup.test @@ -0,0 +1,154 @@ +# +# The signal handler thread can use various different runtime resources when +# processing a SIGHUP (e.g. master-info information), as the logic calls into +# reload_acl_and_cache(). This test ensures that SIGHUP processing, when +# concurrent with server shutdown, the shutdown logic must wait for the SIGHUP +# processing to finish before cleaning up any resources. +# +# Additionally, the error case is tested such that the signal handler thread +# takes too long processing a SIGHUP, and the main mysqld thread must skip its +# wait and output a warning. +# +# Note the SIGHUP is sent via the command-line kill program via a perl script. +# +# References: +# MDEV-30260: Slave crashed:reload_acl_and_cache during shutdown +# + +--source include/not_windows.inc +--source include/not_embedded.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +# Binlog format doesn't matter +--source include/have_binlog_format_statement.inc +--source include/master-slave.inc + +# For error test case which forces timeout +--connection slave +set statement sql_log_bin=0 for call mtr.add_suppression("Signal handler thread did not exit in a timely manner"); + + +--echo # +--echo # Main test +--connection master +create table t1 (a int); +insert into t1 values (1); +--source include/save_master_gtid.inc + +--connection slave +--source include/sync_with_master_gtid.inc + +# Make signal handler handle SIGHUP.. +set @@global.debug_dbug= "+d,hold_sighup_log_refresh"; +--let KILL_NODE_PIDFILE = `SELECT @@pid_file` +--perl + my $kill_sig = $ENV{'KILL_SIGNAL_VALUE'}; + my $pid_filename = $ENV{'KILL_NODE_PIDFILE'}; + my $mysqld_pid = `cat $pid_filename`; + chomp($mysqld_pid); + system("kill -HUP $mysqld_pid"); + exit(0); +EOF + +--echo # Waiting for sighup to reach reload_acl_and_cache.. +set debug_sync="now wait_for in_reload_acl_and_cache"; +--echo # Signalling signal handler to proceed to sleep before REFRESH_HOSTS +set debug_sync="now signal refresh_logs"; + +# ..while we are shutting down +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +--echo # Starting shutdown (note this will take 3+ seconds due to DBUG my_sleep in reload_acl_and_cache) +shutdown; + +--source include/wait_until_disconnected.inc +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: --skip-slave-start=0 +EOF + +--connection server_2 +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection slave +--enable_reconnect +--source include/wait_until_connected_again.inc + +--let $assert_text= Ensure Mariadbd did not segfault when shutting down +--let $assert_select= got signal 11 +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.2.err +--let $assert_count= 0 +--let $assert_only_after = CURRENT_TEST: rpl.rpl_shutdown_sighup +--source include/assert_grep.inc + +--connection master +--sync_slave_with_master + + +--echo # +--echo # Error testcase to ensure an error message is shown if the signal +--echo # takes longer than the timeout while processing the SIGHUP + +--connection slave +set @@global.debug_dbug= "+d,force_sighup_processing_timeout"; +set @@global.debug_dbug= "+d,hold_sighup_log_refresh"; + +--connection master +insert into t1 values (1); +--source include/save_master_gtid.inc + +--connection slave +--source include/sync_with_master_gtid.inc + +# Make signal handler handle SIGHUP.. +--let KILL_NODE_PIDFILE = `SELECT @@pid_file` +--perl + my $kill_sig = $ENV{'KILL_SIGNAL_VALUE'}; + my $pid_filename = $ENV{'KILL_NODE_PIDFILE'}; + my $mysqld_pid = `cat $pid_filename`; + chomp($mysqld_pid); + system("kill -HUP $mysqld_pid"); + exit(0); +EOF +--echo # Waiting for sighup to reach reload_acl_and_cache.. +set debug_sync="now wait_for in_reload_acl_and_cache"; +--echo # Signalling signal handler to proceed to sleep before REFRESH_HOSTS +set debug_sync="now signal refresh_logs"; + +# ..while we are shutting down +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +--echo # Starting shutdown (note this will take 3+ seconds due to DBUG my_sleep in reload_acl_and_cache) +shutdown; + +--source include/wait_until_disconnected.inc +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: --skip-slave-start=0 +EOF + +--connection server_2 +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection slave +--enable_reconnect +--source include/wait_until_connected_again.inc + +--let $assert_text= Ensure warning is issued that signal handler thread is still processing +--let $assert_select= Signal handler thread did not exit in a timely manner. +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.2.err +--let $assert_count= 1 +--let $assert_only_after = CURRENT_TEST: rpl.rpl_shutdown_sighup +--source include/assert_grep.inc + + +--echo # +--echo # Cleanup +--connection master +drop table t1; + +--source include/rpl_end.inc +--echo # End of rpl_shutdown_sighup.test diff --git a/mysql-test/suite/rpl/t/rpl_skip_error.test b/mysql-test/suite/rpl/t/rpl_skip_error.test index d3ef834e8ec..ee11ce5ac92 100644 --- a/mysql-test/suite/rpl/t/rpl_skip_error.test +++ b/mysql-test/suite/rpl/t/rpl_skip_error.test @@ -3,7 +3,11 @@ # Verify that --slave-skip-errors works correctly. The error messages # specified by --slave-skip-errors on slave should be ignored. If # such errors occur, they should not be reported and not cause the -# slave to stop. +# slave to stop. If a skipped-due-to-error statement is a part of a +# larger transaction, and the error is not a deadlock error, the rest +# of the transaction should still commit, with just the errored statement +# ignored (note transactions which are skipped due to deadlocks are +# rolled back fully, see rpl_temporary_error2_skip_all.test). # # ==== Method ==== # @@ -164,6 +168,42 @@ let $current_skipped_error= query_get_value(show global status like "Slave_skipp --echo **** We cannot execute a select as there are differences in the --echo **** behavior between STMT and RBR. + +--echo **** +--echo **** Ensure transactions which are skipped due to encountering a +--echo **** non-deadlock error which is present in --slave-skip-errors result +--echo **** in partially committed transactions +# Slave will insert 3 first, and master will insert 3 within a larger trx +--let $value_preexisting_on_slave= 3 + +--connection master +CREATE TABLE t3 (a INT UNIQUE) ENGINE=InnoDB; + +--sync_slave_with_master +--connection slave +--eval INSERT INTO t3 VALUES ($value_preexisting_on_slave) + +--connection master +BEGIN; +INSERT INTO t3 VALUES (1); +INSERT INTO t3 VALUES (2); +--eval INSERT INTO t3 VALUES ($value_preexisting_on_slave) +INSERT INTO t3 VALUES (4); +COMMIT; +--sync_slave_with_master + +--echo **** Master and slave tables should have the same data, due to the +--echo **** partially replicated transaction's data overlapping with the data +--echo **** that pre-existed on the slave. That is, despite the transaction +--echo **** consisting of 4 statements, the errored statement should be ignored +--echo **** and the other 3 should commit successfully. +let $diff_tables=master:t3,slave:t3; +source include/diff_tables.inc; + +--connection master +DROP TABLE t3; + + --echo ==== Clean Up ==== connection master; diff --git a/mysql-test/suite/rpl/t/rpl_sync.test b/mysql-test/suite/rpl/t/rpl_sync.test index 1e2ec2ca83b..3dd99e736f2 100644 --- a/mysql-test/suite/rpl/t/rpl_sync.test +++ b/mysql-test/suite/rpl/t/rpl_sync.test @@ -82,7 +82,7 @@ print FILE "failure"; close ($file); EOF ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.2.expect SET SESSION debug_dbug="d,crash_before_rotate_relaylog"; --error 2013 FLUSH LOGS; @@ -130,7 +130,7 @@ print FILE @content; close FILE; EOF ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +--write_line restart $MYSQLTEST_VARDIR/tmp/mysqld.2.expect SET SESSION debug_dbug="d,crash_before_rotate_relaylog"; --error 2013 FLUSH LOGS; diff --git a/mysql-test/suite/rpl/t/rpl_temporary_error2.test b/mysql-test/suite/rpl/t/rpl_temporary_error2.test index 49194c5d914..3537499d562 100644 --- a/mysql-test/suite/rpl/t/rpl_temporary_error2.test +++ b/mysql-test/suite/rpl/t/rpl_temporary_error2.test @@ -64,7 +64,14 @@ ROLLBACK; --connection slave --sync_with_master SELECT * FROM t1 ORDER BY a; ---echo * There will be two rows in t2 due to the retry. +if (!$ignored_db_deadlock) +{ + --echo * There will be two rows in t2 due to the retry. +} +if ($ignored_db_deadlock) +{ + --echo * There will be one row in t2 because the ignored deadlock does not retry. +} SELECT * FROM t2 ORDER BY a; let $new_retry= query_get_value(SHOW STATUS LIKE 'Slave_retried_transactions', Value, 1); --disable_query_log diff --git a/mysql-test/suite/rpl/t/rpl_temporary_error2_skip_all-slave.opt b/mysql-test/suite/rpl/t/rpl_temporary_error2_skip_all-slave.opt new file mode 100644 index 00000000000..a9ddd73510c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temporary_error2_skip_all-slave.opt @@ -0,0 +1 @@ +--slave-skip-errors=all diff --git a/mysql-test/suite/rpl/t/rpl_temporary_error2_skip_all.test b/mysql-test/suite/rpl/t/rpl_temporary_error2_skip_all.test new file mode 100644 index 00000000000..6801bf184d5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temporary_error2_skip_all.test @@ -0,0 +1,3 @@ +--source include/have_binlog_format_row.inc +--let $ignored_db_deadlock= 1 +--source rpl_temporary_error2.test diff --git a/mysql-test/suite/sys_vars/r/debug_dbug_utf16le.result b/mysql-test/suite/sys_vars/r/debug_dbug_utf16le.result new file mode 100644 index 00000000000..83b378f2adf --- /dev/null +++ b/mysql-test/suite/sys_vars/r/debug_dbug_utf16le.result @@ -0,0 +1,31 @@ +# +# Start of 10.5 tests +# +# +# MDEV-28366 GLOBAL debug_dbug setting affected by collation_connection=utf16... +# +SET NAMES utf8; +SET collation_connection=utf16le_general_ci; +SET debug_dbug='d,any_random_string'; +SELECT @@debug_dbug; +@@debug_dbug +d,any_random_string +SET debug_dbug=CONCAT('d,', _latin1 0xDF); +SELECT @@debug_dbug; +@@debug_dbug +d,ß +SELECT HEX(@@debug_dbug); +HEX(@@debug_dbug) +642CC39F +SET @@debug_dbug=NULL; +SELECT @@debug_dbug; +@@debug_dbug + +SET @@debug_dbug=DEFAULT; +SELECT @@debug_dbug; +@@debug_dbug + +SET NAMES latin1; +# +# End of 10.5 tests +# diff --git a/mysql-test/suite/sys_vars/r/replicate_rewrite_db.result b/mysql-test/suite/sys_vars/r/replicate_rewrite_db.result index 2dfe3a65133..7a15a270e15 100644 --- a/mysql-test/suite/sys_vars/r/replicate_rewrite_db.result +++ b/mysql-test/suite/sys_vars/r/replicate_rewrite_db.result @@ -85,15 +85,13 @@ SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='replicate VARIABLE_NAME VARIABLE_VALUE REPLICATE_REWRITE_DB db1->db2,db3->db4 # Check restart with appending the value -# restart: --replicate_rewrite_db=X->Y +# restart: --replicate_rewrite_db='X->Y' SELECT @@GLOBAL.replicate_rewrite_db; @@GLOBAL.replicate_rewrite_db -test->rewrite,mysqltest1->test,a->b,X->Y +test->rewrite,mysqltest1->test,a->b,'X->Y' # Check restart with wrong value on CLI [ERROR] Bad syntax in replicate-rewrite-db.Expected syntax is FROM->TO. -# restart: +# restart SELECT @@GLOBAL.replicate_rewrite_db; @@GLOBAL.replicate_rewrite_db test->rewrite,mysqltest1->test,a->b -# Cleanup. -SET @@GLOBAL.replicate_rewrite_db = @save_replicate_rewrite_db; diff --git a/mysql-test/suite/sys_vars/t/allow_suspicious_udfs.test b/mysql-test/suite/sys_vars/t/allow_suspicious_udfs.test index 9179cfbef4d..f5645e01229 100644 --- a/mysql-test/suite/sys_vars/t/allow_suspicious_udfs.test +++ b/mysql-test/suite/sys_vars/t/allow_suspicious_udfs.test @@ -5,10 +5,10 @@ SELECT @@allow_suspicious_udfs AS EXPECT_0; # Restart the server the server with "--allow-suspicious-udfs" option ---let $restart_parameters = "--allow-suspicious-udfs" +--let $restart_parameters = --allow-suspicious-udfs --source include/restart_mysqld.inc SELECT @@allow_suspicious_udfs AS EXPECT_1; # Disable "--allow-suspicious-udfs" to restore the original state ---let $restart_parameters = "--skip-allow-suspicious-udfs" +--let $restart_parameters = --skip-allow-suspicious-udfs --source include/restart_mysqld.inc diff --git a/mysql-test/suite/sys_vars/t/debug_dbug_utf16le.test b/mysql-test/suite/sys_vars/t/debug_dbug_utf16le.test new file mode 100644 index 00000000000..0c4d8f92e93 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/debug_dbug_utf16le.test @@ -0,0 +1,29 @@ +--source include/have_debug.inc +--source include/have_utf16.inc + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-28366 GLOBAL debug_dbug setting affected by collation_connection=utf16... +--echo # + +SET NAMES utf8; +SET collation_connection=utf16le_general_ci; +SET debug_dbug='d,any_random_string'; +SELECT @@debug_dbug; +SET debug_dbug=CONCAT('d,', _latin1 0xDF); +SELECT @@debug_dbug; +SELECT HEX(@@debug_dbug); + +SET @@debug_dbug=NULL; +SELECT @@debug_dbug; + +SET @@debug_dbug=DEFAULT; +SELECT @@debug_dbug; +SET NAMES latin1; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/suite/sys_vars/t/replicate_rewrite_db.test b/mysql-test/suite/sys_vars/t/replicate_rewrite_db.test index 7fbaab1f260..5a9537f1da2 100644 --- a/mysql-test/suite/sys_vars/t/replicate_rewrite_db.test +++ b/mysql-test/suite/sys_vars/t/replicate_rewrite_db.test @@ -63,7 +63,7 @@ SELECT @@GLOBAL.replicate_rewrite_db; SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='replicate_rewrite_db'; --echo # Check restart with appending the value ---let $restart_parameters = "--replicate_rewrite_db='X->Y'" +--let $restart_parameters = --replicate_rewrite_db='X->Y' --source include/restart_mysqld.inc SELECT @@GLOBAL.replicate_rewrite_db; @@ -76,9 +76,6 @@ SELECT @@GLOBAL.replicate_rewrite_db; --replace_regex /mysqld/mariadbd/ /\d\d\d\d-\d*-\d* *\d*:\d*:\d* \d* // --cat_file $MYSQL_TMP_DIR/mysqld--replicate.err # Restart the server with the default options ---let $restart_parameters = "" +--let $restart_parameters = --source include/start_mysqld.inc SELECT @@GLOBAL.replicate_rewrite_db; - ---echo # Cleanup. -SET @@GLOBAL.replicate_rewrite_db = @save_replicate_rewrite_db; diff --git a/mysys/errors.c b/mysys/errors.c index d88540fe277..a8be37bf2b6 100644 --- a/mysys/errors.c +++ b/mysys/errors.c @@ -112,6 +112,13 @@ void init_glob_errs() } #endif +static void my_space_sleep(uint seconds) +{ + sleep(seconds); +} + +void (*my_sleep_for_space)(uint seconds)= my_space_sleep; + void wait_for_free_space(const char *filename, int errors) { if (errors == 0) @@ -123,7 +130,7 @@ void wait_for_free_space(const char *filename, int errors) MYF(ME_BELL | ME_ERROR_LOG | ME_WARNING), MY_WAIT_FOR_USER_TO_FIX_PANIC, MY_WAIT_GIVE_USER_A_MESSAGE * MY_WAIT_FOR_USER_TO_FIX_PANIC ); - (void) sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC); + my_sleep_for_space(MY_WAIT_FOR_USER_TO_FIX_PANIC); } const char **get_global_errmsgs(int nr __attribute__((unused))) diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index da798005a3a..6b480dae0e1 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -172,7 +172,7 @@ static void validate_value(const char *key, const char *value, #define validate_value(key, value, filename) (void)filename #endif -#define SET_HO_ERROR_AND_CONTINUE(e) { ho_error= (e); continue; } +#define SET_HO_ERROR_AND_CONTINUE(e) { ho_error= (e); (*argc)--; continue; } /** Handle command line options. @@ -903,7 +903,7 @@ static int setval(const struct my_option *opts, void *value, char *argument, } if (err) { - res= EXIT_UNKNOWN_SUFFIX; + res= err; goto ret; }; } @@ -1038,7 +1038,7 @@ static inline ulonglong eval_num_suffix(char *suffix, int *error) case 'E': return 1ULL << 60; default: - *error= 1; + *error= EXIT_UNKNOWN_SUFFIX; return 0ULL; } } @@ -1064,15 +1064,18 @@ static longlong eval_num_suffix_ll(char *argument, if (errno == ERANGE) { my_getopt_error_reporter(ERROR_LEVEL, - "Incorrect integer value: '%s'", argument); - *error= 1; + "Integer value out of range for int64:" + " '%s' for %s", + argument, option_name); + *error= EXIT_ARGUMENT_INVALID; DBUG_RETURN(0); } num*= eval_num_suffix(endchar, error); if (*error) - fprintf(stderr, - "Unknown suffix '%c' used for variable '%s' (value '%s')\n", - *endchar, option_name, argument); + my_getopt_error_reporter(ERROR_LEVEL, + "Unknown suffix '%c' used for variable '%s' (value '%s'). " + "Legal suffix characters are: K, M, G, T, P, E", + *endchar, option_name, argument); DBUG_RETURN(num); } @@ -1095,7 +1098,7 @@ static ulonglong eval_num_suffix_ull(char *argument, my_getopt_error_reporter(ERROR_LEVEL, "Incorrect unsigned value: '%s' for %s", argument, option_name); - *error= 1; + *error= EXIT_ARGUMENT_INVALID; DBUG_RETURN(0); } *error= 0; @@ -1104,15 +1107,18 @@ static ulonglong eval_num_suffix_ull(char *argument, if (errno == ERANGE) { my_getopt_error_reporter(ERROR_LEVEL, - "Incorrect integer value: '%s' for %s", + "Integer value out of range for uint64:" + " '%s' for %s", argument, option_name); - *error= 1; + *error= EXIT_ARGUMENT_INVALID; DBUG_RETURN(0); } num*= eval_num_suffix(endchar, error); if (*error) my_getopt_error_reporter(ERROR_LEVEL, - "Unknown suffix '%c' used for variable '%s' (value '%s')", + "Unknown suffix '%c' used for variable '%s'" + " (value '%s')." + " Legal suffix characters are: K, M, G, T, P, E", *endchar, option_name, argument); DBUG_RETURN(num); } @@ -1132,6 +1138,8 @@ static ulonglong eval_num_suffix_ull(char *argument, static longlong getopt_ll(char *arg, const struct my_option *optp, int *err) { longlong num=eval_num_suffix_ll(arg, err, (char*) optp->name); + if (*err) + return(0); return getopt_ll_limit_value(num, optp, NULL); } @@ -1209,6 +1217,8 @@ longlong getopt_ll_limit_value(longlong num, const struct my_option *optp, static ulonglong getopt_ull(char *arg, const struct my_option *optp, int *err) { ulonglong num= eval_num_suffix_ull(arg, err, (char*) optp->name); + if (*err) + return(0); return getopt_ull_limit_value(num, optp, NULL); } diff --git a/plugin/auth_ed25519/ref10/fe_mul.c b/plugin/auth_ed25519/ref10/fe_mul.c index 26ca8b3682d..8ccad3c30d8 100644 --- a/plugin/auth_ed25519/ref10/fe_mul.c +++ b/plugin/auth_ed25519/ref10/fe_mul.c @@ -1,5 +1,6 @@ #include "fe.h" #include "crypto_int64.h" +#include "crypto_uint64.h" /* h = f * g @@ -179,16 +180,16 @@ void fe_mul(fe h,const fe f,const fe g) crypto_int64 h7 = f0g7+f1g6 +f2g5 +f3g4 +f4g3 +f5g2 +f6g1 +f7g0 +f8g9_19+f9g8_19; crypto_int64 h8 = f0g8+f1g7_2 +f2g6 +f3g5_2 +f4g4 +f5g3_2 +f6g2 +f7g1_2 +f8g0 +f9g9_38; crypto_int64 h9 = f0g9+f1g8 +f2g7 +f3g6 +f4g5 +f5g4 +f6g3 +f7g2 +f8g1 +f9g0 ; - crypto_int64 carry0; - crypto_int64 carry1; - crypto_int64 carry2; - crypto_int64 carry3; - crypto_int64 carry4; - crypto_int64 carry5; - crypto_int64 carry6; - crypto_int64 carry7; - crypto_int64 carry8; - crypto_int64 carry9; + crypto_uint64 carry0; + crypto_uint64 carry1; + crypto_uint64 carry2; + crypto_uint64 carry3; + crypto_uint64 carry4; + crypto_uint64 carry5; + crypto_uint64 carry6; + crypto_uint64 carry7; + crypto_uint64 carry8; + crypto_uint64 carry9; /* |h0| <= (1.65*1.65*2^52*(1+19+19+19+19)+1.65*1.65*2^50*(38+38+38+38+38)) diff --git a/plugin/auth_ed25519/ref10/fe_sq.c b/plugin/auth_ed25519/ref10/fe_sq.c index 8dd119841c6..3c718033a0a 100644 --- a/plugin/auth_ed25519/ref10/fe_sq.c +++ b/plugin/auth_ed25519/ref10/fe_sq.c @@ -1,5 +1,6 @@ #include "fe.h" #include "crypto_int64.h" +#include "crypto_uint64.h" /* h = f * f @@ -106,16 +107,16 @@ void fe_sq(fe h,const fe f) crypto_int64 h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38; crypto_int64 h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4 +f9f9_38; crypto_int64 h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2; - crypto_int64 carry0; - crypto_int64 carry1; - crypto_int64 carry2; - crypto_int64 carry3; - crypto_int64 carry4; - crypto_int64 carry5; - crypto_int64 carry6; - crypto_int64 carry7; - crypto_int64 carry8; - crypto_int64 carry9; + crypto_uint64 carry0; + crypto_uint64 carry1; + crypto_uint64 carry2; + crypto_uint64 carry3; + crypto_uint64 carry4; + crypto_uint64 carry5; + crypto_uint64 carry6; + crypto_uint64 carry7; + crypto_uint64 carry8; + crypto_uint64 carry9; carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; diff --git a/plugin/auth_ed25519/ref10/fe_sq2.c b/plugin/auth_ed25519/ref10/fe_sq2.c index 026ed3aacf5..97c03cf4899 100644 --- a/plugin/auth_ed25519/ref10/fe_sq2.c +++ b/plugin/auth_ed25519/ref10/fe_sq2.c @@ -1,5 +1,6 @@ #include "fe.h" #include "crypto_int64.h" +#include "crypto_uint64.h" /* h = 2 * f * f @@ -106,16 +107,16 @@ void fe_sq2(fe h,const fe f) crypto_int64 h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38; crypto_int64 h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4 +f9f9_38; crypto_int64 h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2; - crypto_int64 carry0; - crypto_int64 carry1; - crypto_int64 carry2; - crypto_int64 carry3; - crypto_int64 carry4; - crypto_int64 carry5; - crypto_int64 carry6; - crypto_int64 carry7; - crypto_int64 carry8; - crypto_int64 carry9; + crypto_uint64 carry0; + crypto_uint64 carry1; + crypto_uint64 carry2; + crypto_uint64 carry3; + crypto_uint64 carry4; + crypto_uint64 carry5; + crypto_uint64 carry6; + crypto_uint64 carry7; + crypto_uint64 carry8; + crypto_uint64 carry9; h0 += h0; h1 += h1; diff --git a/plugin/auth_ed25519/ref10/fe_tobytes.c b/plugin/auth_ed25519/ref10/fe_tobytes.c index 0a63baf9c17..a4dff2c1574 100644 --- a/plugin/auth_ed25519/ref10/fe_tobytes.c +++ b/plugin/auth_ed25519/ref10/fe_tobytes.c @@ -1,4 +1,5 @@ #include "fe.h" +#include "crypto_uint32.h" /* Preconditions: @@ -38,16 +39,16 @@ void fe_tobytes(unsigned char *s,const fe h) crypto_int32 h8 = h[8]; crypto_int32 h9 = h[9]; crypto_int32 q; - crypto_int32 carry0; - crypto_int32 carry1; - crypto_int32 carry2; - crypto_int32 carry3; - crypto_int32 carry4; - crypto_int32 carry5; - crypto_int32 carry6; - crypto_int32 carry7; - crypto_int32 carry8; - crypto_int32 carry9; + crypto_uint32 carry0; + crypto_uint32 carry1; + crypto_uint32 carry2; + crypto_uint32 carry3; + crypto_uint32 carry4; + crypto_uint32 carry5; + crypto_uint32 carry6; + crypto_uint32 carry7; + crypto_uint32 carry8; + crypto_uint32 carry9; q = (19 * h9 + (((crypto_int32) 1) << 24)) >> 25; q = (h0 + q) >> 26; @@ -87,32 +88,32 @@ void fe_tobytes(unsigned char *s,const fe h) s[0] = h0 >> 0; s[1] = h0 >> 8; s[2] = h0 >> 16; - s[3] = (h0 >> 24) | (h1 << 2); + s[3] = (h0 >> 24) | ((crypto_uint32)h1 << 2); s[4] = h1 >> 6; s[5] = h1 >> 14; - s[6] = (h1 >> 22) | (h2 << 3); + s[6] = (h1 >> 22) | ((crypto_uint32)h2 << 3); s[7] = h2 >> 5; s[8] = h2 >> 13; - s[9] = (h2 >> 21) | (h3 << 5); + s[9] = (h2 >> 21) | ((crypto_uint32)h3 << 5); s[10] = h3 >> 3; s[11] = h3 >> 11; - s[12] = (h3 >> 19) | (h4 << 6); + s[12] = (h3 >> 19) | ((crypto_uint32)h4 << 6); s[13] = h4 >> 2; s[14] = h4 >> 10; s[15] = h4 >> 18; s[16] = h5 >> 0; s[17] = h5 >> 8; s[18] = h5 >> 16; - s[19] = (h5 >> 24) | (h6 << 1); + s[19] = (h5 >> 24) | ((crypto_uint32)h6 << 1); s[20] = h6 >> 7; s[21] = h6 >> 15; - s[22] = (h6 >> 23) | (h7 << 3); + s[22] = (h6 >> 23) | ((crypto_uint32)h7 << 3); s[23] = h7 >> 5; s[24] = h7 >> 13; - s[25] = (h7 >> 21) | (h8 << 4); + s[25] = (h7 >> 21) | ((crypto_uint32)h8 << 4); s[26] = h8 >> 4; s[27] = h8 >> 12; - s[28] = (h8 >> 20) | (h9 << 6); + s[28] = (h8 >> 20) | ((crypto_uint32)h9 << 6); s[29] = h9 >> 2; s[30] = h9 >> 10; s[31] = h9 >> 18; diff --git a/plugin/auth_ed25519/ref10/ge_scalarmult_base.c b/plugin/auth_ed25519/ref10/ge_scalarmult_base.c index 421e4fa0fba..9a4ced2182f 100644 --- a/plugin/auth_ed25519/ref10/ge_scalarmult_base.c +++ b/plugin/auth_ed25519/ref10/ge_scalarmult_base.c @@ -35,7 +35,7 @@ static void select(ge_precomp *t,int pos,signed char b) { ge_precomp minust; unsigned char bnegative = negative(b); - unsigned char babs = b - (((-bnegative) & b) << 1); + unsigned char babs = b - ((unsigned char)((-bnegative) & b) << 1); ge_precomp_0(t); cmov(t,&base[pos][0],equal(babs,1)); diff --git a/plugin/auth_ed25519/ref10/sc_muladd.c b/plugin/auth_ed25519/ref10/sc_muladd.c index 6f1e9d02d60..7bf222be815 100644 --- a/plugin/auth_ed25519/ref10/sc_muladd.c +++ b/plugin/auth_ed25519/ref10/sc_muladd.c @@ -95,29 +95,29 @@ void sc_muladd(unsigned char *s,const unsigned char *a,const unsigned char *b,co crypto_int64 s21; crypto_int64 s22; crypto_int64 s23; - crypto_int64 carry0; - crypto_int64 carry1; - crypto_int64 carry2; - crypto_int64 carry3; - crypto_int64 carry4; - crypto_int64 carry5; - crypto_int64 carry6; - crypto_int64 carry7; - crypto_int64 carry8; - crypto_int64 carry9; - crypto_int64 carry10; - crypto_int64 carry11; - crypto_int64 carry12; - crypto_int64 carry13; - crypto_int64 carry14; - crypto_int64 carry15; - crypto_int64 carry16; - crypto_int64 carry17; - crypto_int64 carry18; - crypto_int64 carry19; - crypto_int64 carry20; - crypto_int64 carry21; - crypto_int64 carry22; + crypto_uint64 carry0; + crypto_uint64 carry1; + crypto_uint64 carry2; + crypto_uint64 carry3; + crypto_uint64 carry4; + crypto_uint64 carry5; + crypto_uint64 carry6; + crypto_uint64 carry7; + crypto_uint64 carry8; + crypto_uint64 carry9; + crypto_uint64 carry10; + crypto_uint64 carry11; + crypto_uint64 carry12; + crypto_uint64 carry13; + crypto_uint64 carry14; + crypto_uint64 carry15; + crypto_uint64 carry16; + crypto_uint64 carry17; + crypto_uint64 carry18; + crypto_uint64 carry19; + crypto_uint64 carry20; + crypto_uint64 carry21; + crypto_uint64 carry22; s0 = c0 + a0*b0; s1 = c1 + a0*b1 + a1*b0; diff --git a/plugin/auth_ed25519/ref10/sc_reduce.c b/plugin/auth_ed25519/ref10/sc_reduce.c index d01f5a5737e..422d94b6faf 100644 --- a/plugin/auth_ed25519/ref10/sc_reduce.c +++ b/plugin/auth_ed25519/ref10/sc_reduce.c @@ -58,23 +58,23 @@ void sc_reduce(unsigned char *s) crypto_int64 s21 = 2097151 & (load_3(s + 55) >> 1); crypto_int64 s22 = 2097151 & (load_4(s + 57) >> 6); crypto_int64 s23 = (load_4(s + 60) >> 3); - crypto_int64 carry0; - crypto_int64 carry1; - crypto_int64 carry2; - crypto_int64 carry3; - crypto_int64 carry4; - crypto_int64 carry5; - crypto_int64 carry6; - crypto_int64 carry7; - crypto_int64 carry8; - crypto_int64 carry9; - crypto_int64 carry10; - crypto_int64 carry11; - crypto_int64 carry12; - crypto_int64 carry13; - crypto_int64 carry14; - crypto_int64 carry15; - crypto_int64 carry16; + crypto_uint64 carry0; + crypto_uint64 carry1; + crypto_uint64 carry2; + crypto_uint64 carry3; + crypto_uint64 carry4; + crypto_uint64 carry5; + crypto_uint64 carry6; + crypto_uint64 carry7; + crypto_uint64 carry8; + crypto_uint64 carry9; + crypto_uint64 carry10; + crypto_uint64 carry11; + crypto_uint64 carry12; + crypto_uint64 carry13; + crypto_uint64 carry14; + crypto_uint64 carry15; + crypto_uint64 carry16; s11 += s23 * 666643; s12 += s23 * 470296; diff --git a/plugin/feedback/feedback.cc b/plugin/feedback/feedback.cc index ba4850f4cba..845e40ccf52 100644 --- a/plugin/feedback/feedback.cc +++ b/plugin/feedback/feedback.cc @@ -339,6 +339,10 @@ static int free(void *p) shutdown_plugin= true; mysql_cond_signal(&sleep_condition); mysql_mutex_unlock(&sleep_mutex); + + for (uint i= 0; i < url_count; i++) + urls[i]->abort(); + pthread_join(sender_thread, NULL); mysql_mutex_destroy(&sleep_mutex); diff --git a/plugin/feedback/feedback.h b/plugin/feedback/feedback.h index 04fe1ab6aa1..6021eb85860 100644 --- a/plugin/feedback/feedback.h +++ b/plugin/feedback/feedback.h @@ -52,6 +52,7 @@ class Url { const char *url() { return full_url.str; } size_t url_length() { return full_url.length; } + virtual void abort() = 0; virtual int send(const char* data, size_t data_length) = 0; virtual int set_proxy(const char *proxy, size_t proxy_len) { diff --git a/plugin/feedback/url_http.cc b/plugin/feedback/url_http.cc index 98116dd04f1..590bb06cc5f 100644 --- a/plugin/feedback/url_http.cc +++ b/plugin/feedback/url_http.cc @@ -37,8 +37,9 @@ static const uint FOR_WRITING= 1; class Url_http: public Url { protected: const LEX_STRING host, port, path; - bool ssl; LEX_STRING proxy_host, proxy_port; + my_socket fd; + bool ssl; bool use_proxy() { @@ -47,7 +48,8 @@ class Url_http: public Url { Url_http(LEX_STRING &url_arg, LEX_STRING &host_arg, LEX_STRING &port_arg, LEX_STRING &path_arg, bool ssl_arg) : - Url(url_arg), host(host_arg), port(port_arg), path(path_arg), ssl(ssl_arg) + Url(url_arg), host(host_arg), port(port_arg), path(path_arg), + fd(INVALID_SOCKET), ssl(ssl_arg) { proxy_host.length= 0; } @@ -60,6 +62,7 @@ class Url_http: public Url { } public: + void abort(); int send(const char* data, size_t data_length); int set_proxy(const char *proxy, size_t proxy_len) { @@ -158,13 +161,18 @@ Url* http_create(const char *url, size_t url_length) return new Url_http(full_url, host, port, path, ssl); } +void Url_http::abort() +{ + if (fd != INVALID_SOCKET) + closesocket(fd); // interrupt I/O waits +} + /* do the vio_write and check that all data were sent ok */ #define write_check(VIO, DATA, LEN) \ (vio_write((VIO), (uchar*)(DATA), (LEN)) != (LEN)) int Url_http::send(const char* data, size_t data_length) { - my_socket fd= INVALID_SOCKET; char buf[1024]; size_t len= 0; @@ -180,6 +188,7 @@ int Url_http::send(const char* data, size_t data_length) return 1; } + DBUG_ASSERT(fd == INVALID_SOCKET); for (addr= addrs; addr != NULL; addr= addr->ai_next) { fd= socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); @@ -208,6 +217,7 @@ int Url_http::send(const char* data, size_t data_length) sql_print_error("feedback plugin: vio_new failed for url '%s'", full_url.str); closesocket(fd); + fd= INVALID_SOCKET; return 1; } @@ -236,6 +246,7 @@ int Url_http::send(const char* data, size_t data_length) free_vio_ssl_acceptor_fd(ssl_fd); closesocket(fd); vio_delete(vio); + fd= INVALID_SOCKET; return 1; } } @@ -334,6 +345,7 @@ int Url_http::send(const char* data, size_t data_length) } #endif + fd= INVALID_SOCKET; return res; } diff --git a/plugin/test_sql_service/test_sql_service.c b/plugin/test_sql_service/test_sql_service.c index 8b326c6fa46..8a9b3dab61c 100644 --- a/plugin/test_sql_service/test_sql_service.c +++ b/plugin/test_sql_service/test_sql_service.c @@ -129,7 +129,7 @@ void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev) static int run_test(MYSQL_THD thd, struct st_mysql_sys_var *var, void *save, struct st_mysql_value *value) { - *(my_bool*) save= 0; /* Set value for sql_service_run_test */ + *(my_bool*)save= 1; // must initialize the return value return (test_passed= (do_tests() == 0)) == 0; } @@ -140,6 +140,7 @@ static int run_sql(MYSQL *mysql, void *save, struct st_mysql_value *value) int len= 0; MYSQL_RES *res; + *(my_bool*)save= 1; // must initialize the return value str= value->val_str(value, NULL, &len); if (mysql_real_query(mysql, str, len)) diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6.result b/plugin/type_inet/mysql-test/type_inet/type_inet6.result index 5ac2657f0b3..d43352dfff2 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6.result @@ -2359,6 +2359,18 @@ Warning 1292 Incorrect inet6 value: '' Warning 1292 Incorrect inet6 value: '' DROP TABLE t1; # +# MDEV-32458 ASAN unknown-crash in Inet6::ascii_to_fbt when casting character string to inet6 +# +CREATE TABLE t1 (c CHAR(3)); +INSERT INTO t1 VALUES ('1:0'),('00:'); +SELECT * FROM t1 WHERE c>CAST('::1' AS INET6); +c +Warnings: +Warning 1292 Incorrect inet6 value: '1:0' +Warning 1292 Incorrect inet6 value: '00:' +DROP TABLE t1; +# End of 10.6 tests +# # MDEV-22256 Assertion `length == pack_length()' failed in Field_timestamp_with_dec::sort_string # SET sql_mode=''; diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6.test b/plugin/type_inet/mysql-test/type_inet/type_inet6.test index 0c56ecfe4bb..cb3d226f9b6 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6.test +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6.test @@ -1701,6 +1701,17 @@ SELECT 1.00 + (b BETWEEN a AND '') AS f FROM t1 ORDER BY f; SELECT 1.00 + (b IN (a,'')) AS f FROM t1 ORDER BY f; DROP TABLE t1; +--echo # +--echo # MDEV-32458 ASAN unknown-crash in Inet6::ascii_to_fbt when casting character string to inet6 +--echo # + +CREATE TABLE t1 (c CHAR(3)); +INSERT INTO t1 VALUES ('1:0'),('00:'); +SELECT * FROM t1 WHERE c>CAST('::1' AS INET6); +DROP TABLE t1; + +--echo # End of 10.6 tests + --echo # --echo # MDEV-22256 Assertion `length == pack_length()' failed in Field_timestamp_with_dec::sort_string --echo # diff --git a/plugin/type_inet/sql_type_inet.cc b/plugin/type_inet/sql_type_inet.cc index 03c8d8133e5..d23073d2b84 100644 --- a/plugin/type_inet/sql_type_inet.cc +++ b/plugin/type_inet/sql_type_inet.cc @@ -229,7 +229,7 @@ bool Inet6::ascii_to_fbt(const char *str, size_t str_length) continue; } - if (!*p || p >= str_end) + if (p >= str_end || !*p) { DBUG_PRINT("error", ("ascii_to_ipv6(%.*s): invalid IPv6 address: " "ending at ':'.", (int) str_length, str)); diff --git a/plugin/versioning/versioning.cc b/plugin/versioning/versioning.cc index 38ebf76256b..a4916e2f9c1 100644 --- a/plugin/versioning/versioning.cc +++ b/plugin/versioning/versioning.cc @@ -36,8 +36,8 @@ public: static Create_func_trt s_singleton; protected: - Create_func_trt() = default; - virtual ~Create_func_trt() = default; + Create_func_trt() = default; + virtual ~Create_func_trt() = default; }; template @@ -132,8 +132,8 @@ public: static Create_func_trt_trx_sees s_singleton; protected: - Create_func_trt_trx_sees() = default; - virtual ~Create_func_trt_trx_sees() = default; + Create_func_trt_trx_sees() = default; + virtual ~Create_func_trt_trx_sees() = default; }; template diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index aa92096b613..bdf64421914 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -693,6 +693,7 @@ int ha_partition::create_partitioning_metadata(const char *path, partition_element *part; DBUG_ENTER("ha_partition::create_partitioning_metadata"); + mark_trx_read_write(); /* We need to update total number of parts since we might write the handler file as part of a partition management command @@ -8643,7 +8644,7 @@ int ha_partition::info(uint flag) file->stats.auto_increment_value); } while (*(++file_array)); - DBUG_ASSERT(auto_increment_value); + DBUG_ASSERT(!all_parts_opened || auto_increment_value); stats.auto_increment_value= auto_increment_value; if (all_parts_opened && auto_inc_is_first_in_idx) { @@ -10924,18 +10925,19 @@ int ha_partition::update_next_auto_inc_val() bool ha_partition::need_info_for_auto_inc() { - handler **file= m_file; DBUG_ENTER("ha_partition::need_info_for_auto_inc"); - do + for (uint i= bitmap_get_first_set(&m_locked_partitions); + i < m_tot_parts; + i= bitmap_get_next_set(&m_locked_partitions, i)) { - if ((*file)->need_info_for_auto_inc()) + if ((m_file[i])->need_info_for_auto_inc()) { /* We have to get new auto_increment values from handler */ part_share->auto_inc_initialized= FALSE; DBUG_RETURN(TRUE); } - } while (*(++file)); + } DBUG_RETURN(FALSE); } diff --git a/sql/handler.cc b/sql/handler.cc index 078b52575f1..1c874492f24 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1617,6 +1617,29 @@ ha_check_and_coalesce_trx_read_only(THD *thd, Ha_trx_info *ha_list, return rw_ha_count; } +#ifdef WITH_WSREP +/** + Check if transaction contains storage engine not supporting + two-phase commit and transaction is read-write. + + @retval + true Transaction contains storage engine not supporting + two phase commit and transaction is read-write + @retval + false otherwise +*/ +static bool wsrep_have_no2pc_rw_ha(Ha_trx_info* ha_list) +{ + for (Ha_trx_info *ha_info=ha_list; ha_info; ha_info= ha_info->next()) + { + handlerton *ht= ha_info->ht(); + // Transaction is read-write and handler does not support 2pc + if (ha_info->is_trx_read_write() && ht->prepare==0) + return true; + } + return false; +} +#endif /* WITH_WSREP */ /** @retval @@ -1829,14 +1852,18 @@ int ha_commit_trans(THD *thd, bool all) */ if (run_wsrep_hooks) { - // This commit involves more than one storage engine and requires - // two phases, but some engines don't support it. - // Issue a message to the client and roll back the transaction. - if (trans->no_2pc && rw_ha_count > 1) + // This commit involves storage engines that do not support two phases. + // We allow read only transactions to such storage engines but not + // read write transactions. + if (trans->no_2pc && rw_ha_count > 1 && wsrep_have_no2pc_rw_ha(trans->ha_list)) { - // REPLACE|INSERT INTO ... SELECT uses TOI for MyISAM|Aria - if (WSREP(thd) && thd->wsrep_cs().mode() != wsrep::client_state::m_toi) - { + // This commit involves more than one storage engine and requires + // two phases, but some engines don't support it. + // Issue a message to the client and roll back the transaction. + + // 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; @@ -5565,8 +5592,6 @@ handler::ha_create_partitioning_metadata(const char *name, DBUG_ASSERT(m_lock_type == F_UNLCK || (!old_name && strcmp(name, table_share->path.str))); - - mark_trx_read_write(); return create_partitioning_metadata(name, old_name, action_flag); } @@ -7648,7 +7673,16 @@ int handler::ha_write_row(const uchar *buf) m_lock_type == F_WRLCK); DBUG_ENTER("handler::ha_write_row"); DEBUG_SYNC_C("ha_write_row_start"); - +#ifdef WITH_WSREP + DBUG_EXECUTE_IF("wsrep_ha_write_row", + { + const char act[]= + "now " + "SIGNAL wsrep_ha_write_row_reached " + "WAIT_FOR wsrep_ha_write_row_continue"; + DBUG_ASSERT(!debug_sync_set_action(ha_thd(), STRING_WITH_LEN(act))); + }); +#endif /* WITH_WSREP */ if ((error= ha_check_overlaps(NULL, buf))) DBUG_RETURN(error); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 64419605a6f..b8cf27dff03 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1404,7 +1404,13 @@ bool Item_in_optimizer::fix_left(THD *thd) eval_not_null_tables(NULL); with_flags|= (args[0]->with_flags | (args[1]->with_flags & item_with_t::SP_VAR)); - if ((const_item_cache= args[0]->const_item())) + + /* + If left expression is a constant, cache its value. + But don't do that if that involves computing a subquery, as we are in a + prepare-phase rewrite. + */ + if ((const_item_cache= args[0]->const_item()) && !args[0]->with_subquery()) { cache->store(args[0]); cache->cache_value(); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 3d5710cd226..de3f0f9978a 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -3516,13 +3516,11 @@ template class LI, typename T> class Item_equal_iterator { protected: Item_equal *item_equal; - Item *curr_item; + Item *curr_item= nullptr; public: Item_equal_iterator(Item_equal &item_eq) - :LI (item_eq.equal_items) + :LI (item_eq.equal_items), item_equal(&item_eq) { - curr_item= NULL; - item_equal= &item_eq; if (item_eq.with_const) { LI *list_it= this; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index f06f5324444..789864c19fb 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1641,15 +1641,16 @@ String *Item_func_regexp_replace::val_str_internal(String *str, LEX_CSTRING src, rpl; size_t startoffset= 0; - if ((null_value= - (!(source= args[0]->val_str(&tmp0)) || - !(replace= args[2]->val_str_null_to_empty(&tmp2, null_to_empty)) || - re.recompile(args[1])))) - return (String *) 0; - + source= args[0]->val_str(&tmp0); + if (!source) + goto err; + replace= args[2]->val_str_null_to_empty(&tmp2, null_to_empty); + if (!replace || re.recompile(args[1])) + goto err; if (!(source= re.convert_if_needed(source, &re.subject_converter)) || !(replace= re.convert_if_needed(replace, &re.replace_converter))) goto err; + null_value= false; source->get_value(&src); replace->get_value(&rpl); @@ -1695,7 +1696,7 @@ String *Item_func_regexp_replace::val_str_internal(String *str, err: null_value= true; - return (String *) 0; + return nullptr; } @@ -1831,13 +1832,21 @@ bool Item_func_insert::fix_length_and_dec(THD *thd) String *Item_str_conv::val_str(String *str) { DBUG_ASSERT(fixed()); - String *res; - size_t alloced_length, len; + String *res= args[0]->val_str(&tmp_value); - if ((null_value= (!(res= args[0]->val_str(&tmp_value)) || - str->alloc((alloced_length= res->length() * multiply))))) - return 0; + if (!res) + { + err: + null_value= true; + return nullptr; + } + size_t alloced_length= res->length() * multiply, len; + + if (str->alloc((alloced_length))) + goto err; + + null_value= false; len= converter(collation.collation, (char*) res->ptr(), res->length(), (char*) str->ptr(), alloced_length); DBUG_ASSERT(len <= alloced_length); @@ -4964,6 +4973,11 @@ void Item_func_dyncol_create::print_arguments(String *str, { str->append(STRING_WITH_LEN(" charset ")); str->append(defs[i].cs->cs_name); + if (Charset(defs[i].cs).can_have_collate_clause()) + { + str->append(STRING_WITH_LEN(" collate ")); + str->append(defs[i].cs->coll_name); + } str->append(' '); } break; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index b33ea5fc89d..0a37a2ecf53 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -568,6 +568,9 @@ void Item_subselect::recalc_used_tables(st_select_lex *new_parent, This measure is used instead of JOIN::read_time, because it is considered to be much more reliable than the cost estimate. + Note: the logic in this function must agree with + JOIN::init_join_cache_and_keyread(). + @return true if the subquery is expensive @return false otherwise */ diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index a53e89cc8e3..0ac75f903e9 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -3507,6 +3507,24 @@ bool Item_func_timediff::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzy if (l_time1.neg != l_time2.neg) l_sign= -l_sign; + if (l_time1.time_type == MYSQL_TIMESTAMP_TIME) + { + /* + In case of TIME-alike arguments: + TIMEDIFF('38:59:59', '839:00:00') + let's truncate extra fractional seconds that might appear if the argument + values were out of the supported TIME range. For example, args[n]->get_time() + for the string literal '839:00:00' returns TIME'838:59:59.999999'. + The fractional part must be truncated according to this->decimals, + to avoid returning more fractional seconds than it was detected + during this->fix_length_and_dec(). + Note, the thd rounding mode should not be important here, as we're removing + redundant digits from the maximum possible value: '838:59:59.999999'. + */ + my_time_trunc(&l_time1, decimals); + my_time_trunc(&l_time2, decimals); + } + if (calc_time_diff(&l_time1, &l_time2, l_sign, &l_time3, fuzzydate)) return (null_value= 1); diff --git a/sql/log.cc b/sql/log.cc index fea8c67fb64..0c3475d9f34 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -8183,9 +8183,9 @@ MYSQL_BIN_LOG::queue_for_group_commit(group_commit_entry *orig_entry) if (entry->cache_mngr->using_xa) { - DEBUG_SYNC(entry->thd, "commit_before_prepare_ordered"); + DEBUG_SYNC(orig_entry->thd, "commit_before_prepare_ordered"); run_prepare_ordered(entry->thd, entry->all); - DEBUG_SYNC(entry->thd, "commit_after_prepare_ordered"); + DEBUG_SYNC(orig_entry->thd, "commit_after_prepare_ordered"); } if (cur) diff --git a/sql/log_event.cc b/sql/log_event.cc index 215ee317b47..bf3d93c903d 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2645,6 +2645,11 @@ Gtid_log_event::Gtid_log_event(const uchar *buf, uint event_len, } if (flags2 & (FL_PREPARED_XA | FL_COMPLETED_XA)) { + if (event_len < static_cast(buf - buf_0) + 6) + { + seq_no= 0; + return; + } xid.formatID= uint4korr(buf); buf+= 4; @@ -2653,6 +2658,11 @@ Gtid_log_event::Gtid_log_event(const uchar *buf, uint event_len, buf+= 2; long data_length= xid.bqual_length + xid.gtrid_length; + if (event_len < static_cast(buf - buf_0) + data_length) + { + seq_no= 0; + return; + } memcpy(xid.data, buf, data_length); buf+= data_length; } @@ -2667,8 +2677,11 @@ Gtid_log_event::Gtid_log_event(const uchar *buf, uint event_len, */ if (flags_extra & FL_EXTRA_MULTI_ENGINE_E1) { - DBUG_ASSERT(static_cast(buf - buf_0) < event_len); - + if (event_len < static_cast(buf - buf_0) + 1) + { + seq_no= 0; + return; + } extra_engines= *buf++; DBUG_ASSERT(extra_engines > 0); diff --git a/sql/log_event.h b/sql/log_event.h index a7a0cac3c01..2d9b7cebaf3 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -3733,7 +3733,16 @@ public: { return GTID_HEADER_LEN + ((flags2 & FL_GROUP_COMMIT_ID) ? 2 : 0); } - bool is_valid() const { return seq_no != 0; } + + bool is_valid() const + { + /* + seq_no is set to 0 if the structure of a serialized GTID event does not + align with that as indicated by flags and extra_flags. + */ + return seq_no != 0; + } + #ifdef MYSQL_SERVER bool write(); static int make_compatible_event(String *packet, bool *need_dummy_event, diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index 5030c9afa62..6b72efdd206 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -3725,21 +3725,34 @@ Gtid_log_event::write() write_len= GTID_HEADER_LEN + 2; } - if (flags2 & (FL_PREPARED_XA | FL_COMPLETED_XA)) + if (flags2 & (FL_PREPARED_XA | FL_COMPLETED_XA) + && !DBUG_IF("negate_xid_from_gtid")) { int4store(&buf[write_len], xid.formatID); buf[write_len +4]= (uchar) xid.gtrid_length; buf[write_len +4+1]= (uchar) xid.bqual_length; write_len+= 6; long data_length= xid.bqual_length + xid.gtrid_length; - memcpy(buf+write_len, xid.data, data_length); - write_len+= data_length; + + if (!DBUG_IF("negate_xid_data_from_gtid")) + { + memcpy(buf+write_len, xid.data, data_length); + write_len+= data_length; + } } + + DBUG_EXECUTE_IF("inject_fl_extra_multi_engine_into_gtid", { + flags_extra|= FL_EXTRA_MULTI_ENGINE_E1; + }); if (flags_extra > 0) { buf[write_len]= flags_extra; write_len++; } + DBUG_EXECUTE_IF("inject_fl_extra_multi_engine_into_gtid", { + flags_extra&= ~FL_EXTRA_MULTI_ENGINE_E1; + }); + if (flags_extra & FL_EXTRA_MULTI_ENGINE_E1) { buf[write_len]= extra_engines; @@ -4522,7 +4535,8 @@ int XA_prepare_log_event::do_commit() thd->lex->xid= &xid; if (!one_phase) { - if ((res= thd->wait_for_prior_commit())) + if (thd->is_current_stmt_binlog_disabled() && + (res= thd->wait_for_prior_commit())) return res; thd->lex->sql_command= SQLCOM_XA_PREPARE; @@ -6340,11 +6354,13 @@ static int rows_event_stmt_cleanup(rpl_group_info *rgi, THD * thd) Xid_log_event will come next which will, if some transactional engines are involved, commit the transaction and flush the pending event to the binlog. - If there was a deadlock the transaction should have been rolled back - already. So there should be no need to rollback the transaction. + We check for thd->transaction_rollback_request because it is possible + there was a deadlock that was ignored by slave-skip-errors. Normally, the + deadlock would have been rolled back already. */ - DBUG_ASSERT(! thd->transaction_rollback_request); - error|= (int)(error ? trans_rollback_stmt(thd) : trans_commit_stmt(thd)); + error|= (int) ((error || thd->transaction_rollback_request) + ? trans_rollback_stmt(thd) + : trans_commit_stmt(thd)); /* Now what if this is not a transactional engine? we still need to @@ -7966,6 +7982,7 @@ int Rows_log_event::update_sequence() #if defined(WITH_WSREP) ! WSREP(thd) && #endif + table->in_use->rgi_slave && !(table->in_use->rgi_slave->gtid_ev_flags2 & Gtid_log_event::FL_DDL) && !(old_master= rpl_master_has_bug(thd->rgi_slave->rli, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index bdca3a6b50b..966ba0143b5 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1783,7 +1783,8 @@ static void close_connections(void) "Delaying shutdown to await semi-sync ACK"); } - Events::deinit(); + if (Events::inited) + Events::stop(); slave_prepare_for_shutdown(); ack_receiver.stop(); @@ -1845,6 +1846,12 @@ static void close_connections(void) } /* End of kill phase 2 */ + /* + The signal thread can use server resources, e.g. when processing SIGHUP, + and it must end gracefully before clean_up() + */ + wait_for_signal_thread_to_end(); + DBUG_PRINT("quit",("close_connections thread")); DBUG_VOID_RETURN; } @@ -1921,14 +1928,8 @@ extern "C" void unireg_abort(int exit_code) static void mysqld_exit(int exit_code) { DBUG_ENTER("mysqld_exit"); - /* - Important note: we wait for the signal thread to end, - but if a kill -15 signal was sent, the signal thread did - spawn the kill_server_thread thread, which is running concurrently. - */ rpl_deinit_gtid_waiting(); rpl_deinit_gtid_slave_state(); - wait_for_signal_thread_to_end(); #ifdef WITH_WSREP wsrep_deinit_server(); wsrep_sst_auth_free(); @@ -2010,6 +2011,9 @@ static void clean_up(bool print_message) free_status_vars(); end_thr_alarm(1); /* Free allocated memory */ end_thr_timer(); +#ifndef EMBEDDED_LIBRARY + Events::deinit(); +#endif my_free_open_file_info(); if (defaults_argv) free_defaults(defaults_argv); @@ -2080,16 +2084,32 @@ static void clean_up(bool print_message) */ static void wait_for_signal_thread_to_end() { - uint i; + uint i, n_waits= DBUG_IF("force_sighup_processing_timeout") ? 5 : 100; + int err= 0; /* Wait up to 10 seconds for signal thread to die. We use this mainly to avoid getting warnings that my_thread_end has not been called */ - for (i= 0 ; i < 100 && signal_thread_in_use; i++) + for (i= 0 ; i < n_waits && signal_thread_in_use; i++) { - if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL) == ESRCH) + err= pthread_kill(signal_thread, MYSQL_KILL_SIGNAL); + if (err) break; - my_sleep(100); // Give it time to die + my_sleep(100000); // Give it time to die, .1s per iteration + } + + if (err && err != ESRCH) + { + sql_print_error("Failed to send kill signal to signal handler thread, " + "pthread_kill() errno: %d", + err); + } + + if (i == n_waits && signal_thread_in_use) + { + sql_print_warning("Signal handler thread did not exit in a timely manner. " + "Continuing to wait for it to stop.."); + pthread_join(signal_thread, NULL); } } #endif /*EMBEDDED_LIBRARY*/ @@ -3168,7 +3188,6 @@ static void start_signal_handler(void) (void) pthread_attr_init(&thr_attr); pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_SYSTEM); - (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); (void) my_setstacksize(&thr_attr,my_thread_stack_size); mysql_mutex_lock(&LOCK_start_thread); @@ -3188,18 +3207,6 @@ static void start_signal_handler(void) } -#if defined(USE_ONE_SIGNAL_HAND) -pthread_handler_t kill_server_thread(void *arg __attribute__((unused))) -{ - my_thread_init(); // Initialize new thread - break_connect_loop(); - my_thread_end(); - pthread_exit(0); - return 0; -} -#endif - - /** This threads handles all signals and alarms. */ /* ARGSUSED */ pthread_handler_t signal_hand(void *arg __attribute__((unused))) @@ -3256,7 +3263,7 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused))) int origin; while ((error= my_sigwait(&set, &sig, &origin)) == EINTR) /* no-op */; - if (cleanup_done) + if (abort_loop) { DBUG_PRINT("quit",("signal_handler: calling my_thread_end()")); my_thread_end(); @@ -3279,18 +3286,8 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused))) { /* Delete the instrumentation for the signal thread */ PSI_CALL_delete_current_thread(); -#ifdef USE_ONE_SIGNAL_HAND - pthread_t tmp; - if (unlikely((error= mysql_thread_create(0, /* Not instrumented */ - &tmp, &connection_attrib, - kill_server_thread, - (void*) &sig)))) - sql_print_error("Can't create thread to kill server (errno= %d)", - error); -#else my_sigset(sig, SIG_IGN); break_connect_loop(); // MIT THREAD has a alarm thread -#endif } break; case SIGHUP: @@ -4115,8 +4112,9 @@ static int init_common_variables() SQLCOM_END + 10); #endif - if (get_options(&remaining_argc, &remaining_argv)) - exit(1); + int opt_err; + if ((opt_err= get_options(&remaining_argc, &remaining_argv))) + exit(opt_err); if (IS_SYSVAR_AUTOSIZE(&server_version_ptr)) set_server_version(server_version, sizeof(server_version)); @@ -4980,6 +4978,9 @@ static int init_server_components() error_handler_hook= my_message_sql; proc_info_hook= set_thd_stage_info; + /* Set up hook to handle disk full */ + my_sleep_for_space= mariadb_sleep_for_space; + /* Print source revision hash, as one of the first lines, if not the first in error log, for troubleshooting and debugging purposes @@ -5484,6 +5485,10 @@ static int init_server_components() } #endif +#ifndef EMBEDDED_LIBRARY + start_handle_manager(); +#endif + tc_log= get_tc_log_implementation(); if (tc_log->open(opt_bin_log ? opt_bin_logname : opt_tc_log_file)) @@ -5495,9 +5500,6 @@ static int init_server_components() if (ha_recover(0)) unireg_abort(1); -#ifndef EMBEDDED_LIBRARY - start_handle_manager(); -#endif if (opt_bin_log) { int error; @@ -9296,6 +9298,7 @@ PSI_stage_info stage_user_lock= { 0, "User lock", 0}; PSI_stage_info stage_user_sleep= { 0, "User sleep", 0}; PSI_stage_info stage_verifying_table= { 0, "Verifying table", 0}; PSI_stage_info stage_waiting_for_delay_list= { 0, "Waiting for delay_list", 0}; +PSI_stage_info stage_waiting_for_disk_space= {0, "Waiting for someone to free space", 0}; PSI_stage_info stage_waiting_for_gtid_to_be_written_to_binary_log= { 0, "Waiting for GTID to be written to binary log", 0}; PSI_stage_info stage_waiting_for_handler_insert= { 0, "Waiting for handler insert", 0}; PSI_stage_info stage_waiting_for_handler_lock= { 0, "Waiting for handler lock", 0}; diff --git a/sql/mysqld.h b/sql/mysqld.h index 60cebdefcf7..c8b02c56610 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -651,6 +651,7 @@ extern PSI_stage_info stage_user_sleep; extern PSI_stage_info stage_verifying_table; extern PSI_stage_info stage_waiting_for_ddl; extern PSI_stage_info stage_waiting_for_delay_list; +extern PSI_stage_info stage_waiting_for_disk_space; extern PSI_stage_info stage_waiting_for_flush; extern PSI_stage_info stage_waiting_for_gtid_to_be_written_to_binary_log; extern PSI_stage_info stage_waiting_for_handler_insert; diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index 88287d331ec..b63642a2f0d 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -215,6 +215,13 @@ finish_event_group(rpl_parallel_thread *rpt, uint64 sub_id, signal_error_to_sql_driver_thread(thd, rgi, err); thd->wait_for_commit_ptr= NULL; + /* + Calls to check_duplicate_gtid() must match up with + record_and_update_gtid() (or release_domain_owner() in error case). This + assertion tries to catch any missing release of the domain. + */ + DBUG_ASSERT(rgi->gtid_ignore_duplicate_state != rpl_group_info::GTID_DUPLICATE_OWNER); + mysql_mutex_lock(&entry->LOCK_parallel_entry); /* We need to mark that this event group started its commit phase, in case we @@ -908,7 +915,13 @@ do_retry: }); #endif - rgi->cleanup_context(thd, 1); + /* + We are still applying the event group, even though we will roll it back + and retry it. So for --gtid-ignore-duplicates, keep ownership of the + domain during the retry so another master connection will not try to take + over and duplicate apply the same event group (MDEV-33475). + */ + rgi->cleanup_context(thd, 1, 1 /* keep_domain_owner */); wait_for_pending_deadlock_kill(thd, rgi); thd->reset_killed(); thd->clear_error(); @@ -2405,13 +2418,17 @@ rpl_parallel_thread_pool::copy_pool_for_pfs(Relay_log_info *rli) false Worker not allocated (choose_thread_internal not called) */ static bool handle_split_alter(rpl_parallel_entry *e, - Gtid_log_event *gtid_ev, uint32 *idx, + Gtid_log_event *gtid_ev, + //uint32 *idx, + rpl_parallel_entry::sched_bucket **ptr_cur_thr, //choose_thread_internal specific bool *did_enter_cond, rpl_group_info* rgi, PSI_stage_info *old_stage) { uint16 flags_extra= gtid_ev->flags_extra; bool thread_allocated= false; + uint32 i= 0, *idx= &i; + //Step 1 if (flags_extra & Gtid_log_event::FL_START_ALTER_E1 || //This will arrange finding threads for CA/RA as well @@ -2422,11 +2439,12 @@ static bool handle_split_alter(rpl_parallel_entry *e, j is needed for round robin scheduling, we will start with rpl_thread_idx go till rpl_thread_max and then start with 0 to rpl_thread_idx */ - int j= e->rpl_thread_idx; + auto j= static_cast(e->thread_sched_fifo->head() - e->rpl_threads); // formerly e->rpl_thread_idx; for(uint i= 0; i < e->rpl_thread_max; i++) { - if (!e->rpl_threads[j] || e->rpl_threads[j]->current_owner - != &e->rpl_threads[j] || !e->rpl_threads[j]->current_start_alter_id) + if (!e->rpl_threads[j].thr || + e->rpl_threads[j].thr->current_owner != &e->rpl_threads[j].thr || + !e->rpl_threads[j].thr->current_start_alter_id) { //This condition will hit atleast one time no matter what happens *idx= j; @@ -2437,17 +2455,26 @@ static bool handle_split_alter(rpl_parallel_entry *e, j= j % e->rpl_thread_max; } //We did not find and idx - DBUG_ASSERT(0); - return false; + DBUG_ASSERT(0); + + return false; + idx_found: - e->rpl_thread_idx= *idx; - e->choose_thread_internal(*idx, did_enter_cond, rgi, old_stage); + //e->rpl_thread_idx= *idx; + /* place the found *idx index into the head */ + *ptr_cur_thr= &e->rpl_threads[*idx]; + (*ptr_cur_thr)->unlink(); + e->thread_sched_fifo->append(*ptr_cur_thr); + *ptr_cur_thr= e->thread_sched_fifo->head(); + + e->choose_thread_internal(*ptr_cur_thr, did_enter_cond, rgi, + old_stage); thread_allocated= true; if (flags_extra & Gtid_log_event::FL_START_ALTER_E1) { - mysql_mutex_assert_owner(&e->rpl_threads[*idx]->LOCK_rpl_thread); - e->rpl_threads[e->rpl_thread_idx]->current_start_alter_id= gtid_ev->seq_no; - e->rpl_threads[e->rpl_thread_idx]->current_start_alter_domain_id= + mysql_mutex_assert_owner(&e->rpl_threads[*idx].thr->LOCK_rpl_thread); + e->rpl_threads[*idx].thr->current_start_alter_id= gtid_ev->seq_no; + e->rpl_threads[*idx].thr->current_start_alter_domain_id= gtid_ev->domain_id; /* We are locking LOCK_rpl_thread_pool becuase we are going to update @@ -2463,9 +2490,9 @@ idx_found: } else { - e->rpl_threads[*idx]->reserved_start_alter_thread= true; - e->rpl_threads[*idx]->current_start_alter_id= 0; - e->rpl_threads[*idx]->current_start_alter_domain_id= 0; + e->rpl_threads[*idx].thr->reserved_start_alter_thread= true; + e->rpl_threads[*idx].thr->current_start_alter_id= 0; + e->rpl_threads[*idx].thr->current_start_alter_domain_id= 0; } mysql_mutex_unlock(&global_rpl_thread_pool.LOCK_rpl_thread_pool); } @@ -2476,13 +2503,13 @@ idx_found: //Free the corrosponding rpt current_start_alter_id for(uint i= 0; i < e->rpl_thread_max; i++) { - if(e->rpl_threads[i] && - e->rpl_threads[i]->current_start_alter_id == gtid_ev->sa_seq_no && - e->rpl_threads[i]->current_start_alter_domain_id == gtid_ev->domain_id) + if(e->rpl_threads[i].thr && + e->rpl_threads[i].thr->current_start_alter_id == gtid_ev->sa_seq_no && + e->rpl_threads[i].thr->current_start_alter_domain_id == gtid_ev->domain_id) { mysql_mutex_lock(&global_rpl_thread_pool.LOCK_rpl_thread_pool); - e->rpl_threads[i]->current_start_alter_id= 0; - e->rpl_threads[i]->current_start_alter_domain_id= 0; + e->rpl_threads[i].thr->current_start_alter_id= 0; + e->rpl_threads[i].thr->current_start_alter_domain_id= 0; global_rpl_thread_pool.current_start_alters--; e->pending_start_alters--; DBUG_PRINT("info", ("Commit/Rollback alter id %d", i)); @@ -2497,6 +2524,79 @@ idx_found: } +/* + Check when we have done a complete round of scheduling for workers + 0, 1, ..., (rpl_thread_max-1), in this order. + This often occurs every rpl_thread_max event group, but XA XID dependency + restrictions can cause insertion of extra out-of-order worker scheduling + in-between the normal round-robin scheduling. +*/ +void +rpl_parallel_entry::check_scheduling_generation(sched_bucket *cur) +{ + uint32 idx= static_cast(cur - rpl_threads); + DBUG_ASSERT(cur >= rpl_threads); + DBUG_ASSERT(cur < rpl_threads + rpl_thread_max); + if (idx == current_generation_idx) + { + ++idx; + if (idx >= rpl_thread_max) + { + /* A new generation; all workers have been scheduled at least once. */ + idx= 0; + ++current_generation; + } + current_generation_idx= idx; + } +} + + +rpl_parallel_entry::sched_bucket * +rpl_parallel_entry::check_xa_xid_dependency(xid_t *xid) +{ + uint64 cur_gen= current_generation; + my_off_t i= 0; + while (i < maybe_active_xid.elements) + { + /* + Purge no longer active XID from the list: + + - In generation N, XID might have been scheduled for worker W. + - Events in generation (N+1) might run freely in parallel with W. + - Events in generation (N+2) will have done wait_for_prior_commit for + the event group with XID (or a later one), but the XID might still be + active for a bit longer after wakeup_prior_commit(). + - Events in generation (N+3) will have done wait_for_prior_commit() for + an event in W _after_ the XID, so are sure not to see the XID active. + + Therefore, XID can be safely scheduled to a different worker in + generation (N+3) when last prior use was in generation N (or earlier). + */ + xid_active_generation *a= + dynamic_element(&maybe_active_xid, i, xid_active_generation *); + if (a->generation + 3 <= cur_gen) + { + *a= *((xid_active_generation *)pop_dynamic(&maybe_active_xid)); + continue; + } + if (xid->eq(&a->xid)) + { + /* Update the last used generation and return the match. */ + a->generation= cur_gen; + return a->thr; + } + ++i; + } + /* try to keep allocated memory in the range of [2,10] * initial_chunk_size */ + if (maybe_active_xid.elements <= 2 * active_xid_init_alloc() && + maybe_active_xid.max_element > 10 * active_xid_init_alloc()) + freeze_size(&maybe_active_xid); + + /* No matching XID conflicts. */ + return nullptr; +} + + /* Obtain a worker thread that we can queue an event to. @@ -2529,40 +2629,70 @@ rpl_parallel_entry::choose_thread(rpl_group_info *rgi, bool *did_enter_cond, PSI_stage_info *old_stage, Gtid_log_event *gtid_ev) { - uint32 idx; + sched_bucket *cur_thr; - idx= rpl_thread_idx; if (gtid_ev) { - if (++idx >= rpl_thread_max) - idx= 0; + /* New event group; cycle the thread scheduling buckets round-robin. */ + thread_sched_fifo->push_back(thread_sched_fifo->get()); + //rpl_thread_idx will be updated handle_split_alter - if (handle_split_alter(this, gtid_ev, &idx, did_enter_cond, rgi, old_stage)) - return rpl_threads[idx]; + if (handle_split_alter(this, gtid_ev, &cur_thr, did_enter_cond, rgi, + old_stage)) + return cur_thr->thr; + if (gtid_ev->flags2 & (Gtid_log_event::FL_COMPLETED_XA | Gtid_log_event::FL_PREPARED_XA)) - { - idx= my_hash_sort(&my_charset_bin, gtid_ev->xid.key(), - gtid_ev->xid.key_length()) % rpl_thread_max; + { + if ((cur_thr= check_xa_xid_dependency(>id_ev->xid))) + { + /* + A previously scheduled event group with the same XID might still be + active in a worker, so schedule this event group in the same worker + to avoid a conflict. + */ + cur_thr->unlink(); + thread_sched_fifo->append(cur_thr); + } + else + { + /* Record this XID now active. */ + xid_active_generation *a= + (xid_active_generation *)alloc_dynamic(&maybe_active_xid); + if (!a) + return NULL; + a->thr= cur_thr= thread_sched_fifo->head(); + a->generation= current_generation; + a->xid.set(>id_ev->xid); + } } - rpl_thread_idx= idx; + else + cur_thr= thread_sched_fifo->head(); + + check_scheduling_generation(cur_thr); } - return choose_thread_internal(idx, did_enter_cond, rgi, old_stage); + else + cur_thr= thread_sched_fifo->head(); + + return choose_thread_internal(cur_thr /*idx*/, did_enter_cond, rgi, old_stage); } -rpl_parallel_thread * rpl_parallel_entry::choose_thread_internal(uint idx, - bool *did_enter_cond, rpl_group_info *rgi, - PSI_stage_info *old_stage) +rpl_parallel_thread * +rpl_parallel_entry::choose_thread_internal(sched_bucket *cur_thr, + bool *did_enter_cond, + rpl_group_info *rgi, + PSI_stage_info *old_stage) { - rpl_parallel_thread* thr= rpl_threads[idx]; Relay_log_info *rli= rgi->rli; + rpl_parallel_thread *thr= cur_thr->thr; + if (thr) { *did_enter_cond= false; mysql_mutex_lock(&thr->LOCK_rpl_thread); for (;;) { - if (thr->current_owner != &rpl_threads[idx]) + if (thr->current_owner != &cur_thr->thr) { /* The worker thread became idle, and returned to the free list and @@ -2594,17 +2724,16 @@ rpl_parallel_thread * rpl_parallel_entry::choose_thread_internal(uint idx, and this can cause THD::awake to use the wrong mutex. */ #ifdef ENABLED_DEBUG_SYNC - DBUG_EXECUTE_IF("rpl_parallel_wait_queue_max", - { - debug_sync_set_action(rli->sql_driver_thd, - STRING_WITH_LEN("now SIGNAL wait_queue_ready")); - };); + DBUG_EXECUTE_IF("rpl_parallel_wait_queue_max", { + debug_sync_set_action( + rli->sql_driver_thd, + STRING_WITH_LEN("now SIGNAL wait_queue_ready")); + };); #endif rli->sql_driver_thd->set_time_for_next_stage(); - rli->sql_driver_thd->ENTER_COND(&thr->COND_rpl_thread_queue, - &thr->LOCK_rpl_thread, - &stage_waiting_for_room_in_worker_thread, - old_stage); + rli->sql_driver_thd->ENTER_COND( + &thr->COND_rpl_thread_queue, &thr->LOCK_rpl_thread, + &stage_waiting_for_room_in_worker_thread, old_stage); *did_enter_cond= true; } @@ -2614,11 +2743,11 @@ rpl_parallel_thread * rpl_parallel_entry::choose_thread_internal(uint idx, did_enter_cond, old_stage); my_error(ER_CONNECTION_KILLED, MYF(0)); #ifdef ENABLED_DEBUG_SYNC - DBUG_EXECUTE_IF("rpl_parallel_wait_queue_max", - { - debug_sync_set_action(rli->sql_driver_thd, - STRING_WITH_LEN("now SIGNAL wait_queue_killed")); - };); + DBUG_EXECUTE_IF("rpl_parallel_wait_queue_max", { + debug_sync_set_action( + rli->sql_driver_thd, + STRING_WITH_LEN("now SIGNAL wait_queue_killed")); + };); #endif slave_output_error_info(rgi, rli->sql_driver_thd); return NULL; @@ -2628,9 +2757,10 @@ rpl_parallel_thread * rpl_parallel_entry::choose_thread_internal(uint idx, } } } + if (!thr) - rpl_threads[idx]= thr= global_rpl_thread_pool.get_thread(&rpl_threads[idx], - this); + cur_thr->thr= thr= + global_rpl_thread_pool.get_thread(&cur_thr->thr, this); return thr; } @@ -2645,6 +2775,7 @@ free_rpl_parallel_entry(void *element) dealloc_gco(e->current_gco); e->current_gco= prev_gco; } + delete_dynamic(&e->maybe_active_xid); mysql_cond_destroy(&e->COND_parallel_entry); mysql_mutex_destroy(&e->LOCK_parallel_entry); my_free(e); @@ -2688,17 +2819,37 @@ rpl_parallel::find(uint32 domain_id, Relay_log_info *rli) ulong count= opt_slave_domain_parallel_threads; if (count == 0 || count > opt_slave_parallel_threads) count= opt_slave_parallel_threads; - rpl_parallel_thread **p; + rpl_parallel_entry::sched_bucket *p; + I_List *fifo; if (!my_multi_malloc(PSI_INSTRUMENT_ME, MYF(MY_WME|MY_ZEROFILL), &e, sizeof(*e), &p, count*sizeof(*p), + &fifo, sizeof(*fifo), NULL)) { my_error(ER_OUTOFMEMORY, MYF(0), (int)(sizeof(*e)+count*sizeof(*p))); return NULL; } + /* Initialize a FIFO of scheduled worker threads. */ + e->thread_sched_fifo = new (fifo) I_List; + /* + (We cycle the FIFO _before_ allocating next entry in + rpl_parallel_entry::choose_thread(). So initialize the FIFO with the + highest element at the front, just so that the first event group gets + scheduled on entry 0). + */ + e->thread_sched_fifo-> + push_back(::new (p+count-1) rpl_parallel_entry::sched_bucket); + for (ulong i= 0; i < count-1; ++i) + e->thread_sched_fifo-> + push_back(::new (p+i) rpl_parallel_entry::sched_bucket); e->rpl_threads= p; e->rpl_thread_max= count; + e->current_generation = 0; + e->current_generation_idx = 0; + init_dynamic_array2(PSI_INSTRUMENT_ME, &e->maybe_active_xid, + sizeof(rpl_parallel_entry::xid_active_generation), + 0, e->active_xid_init_alloc(), 0, MYF(0)); e->domain_id= domain_id; e->stop_on_error_sub_id= (uint64)ULONGLONG_MAX; e->pause_sub_id= (uint64)ULONGLONG_MAX; @@ -2768,10 +2919,10 @@ rpl_parallel::wait_for_done(THD *thd, Relay_log_info *rli) mysql_mutex_unlock(&e->LOCK_parallel_entry); for (j= 0; j < e->rpl_thread_max; ++j) { - if ((rpt= e->rpl_threads[j])) + if ((rpt= e->rpl_threads[j].thr)) { mysql_mutex_lock(&rpt->LOCK_rpl_thread); - if (rpt->current_owner == &e->rpl_threads[j]) + if (rpt->current_owner == &e->rpl_threads[j].thr) mysql_cond_signal(&rpt->COND_rpl_thread); mysql_mutex_unlock(&rpt->LOCK_rpl_thread); } @@ -2830,10 +2981,10 @@ rpl_parallel::wait_for_done(THD *thd, Relay_log_info *rli) e= (struct rpl_parallel_entry *)my_hash_element(&domain_hash, i); for (j= 0; j < e->rpl_thread_max; ++j) { - if ((rpt= e->rpl_threads[j])) + if ((rpt= e->rpl_threads[j].thr)) { mysql_mutex_lock(&rpt->LOCK_rpl_thread); - while (rpt->current_owner == &e->rpl_threads[j]) + while (rpt->current_owner == &e->rpl_threads[j].thr) mysql_cond_wait(&rpt->COND_rpl_thread_stop, &rpt->LOCK_rpl_thread); mysql_mutex_unlock(&rpt->LOCK_rpl_thread); } @@ -2891,7 +3042,7 @@ int rpl_parallel_entry::queue_master_restart(rpl_group_info *rgi, Format_description_log_event *fdev) { - uint32 idx; + sched_bucket *cur_thr; rpl_parallel_thread *thr; rpl_parallel_thread::queued_event *qev; Relay_log_info *rli= rgi->rli; @@ -2906,12 +3057,12 @@ rpl_parallel_entry::queue_master_restart(rpl_group_info *rgi, Thus there is no need for the full complexity of choose_thread(). We only need to check if we have a current worker thread, and queue for it if so. */ - idx= rpl_thread_idx; - thr= rpl_threads[idx]; + cur_thr= thread_sched_fifo->head(); + thr= cur_thr->thr; if (!thr) return 0; mysql_mutex_lock(&thr->LOCK_rpl_thread); - if (thr->current_owner != &rpl_threads[idx]) + if (thr->current_owner != &cur_thr->thr) { /* No active worker thread, so no need to queue the master restart. */ mysql_mutex_unlock(&thr->LOCK_rpl_thread); diff --git a/sql/rpl_parallel.h b/sql/rpl_parallel.h index 307d0e3bada..d8ee98f91c6 100644 --- a/sql/rpl_parallel.h +++ b/sql/rpl_parallel.h @@ -344,6 +344,27 @@ struct rpl_parallel_thread_pool { struct rpl_parallel_entry { + /* + A small struct to put worker threads references into a FIFO (using an + I_List) for round-robin scheduling. + */ + struct sched_bucket : public ilink { + sched_bucket() : thr(nullptr) { } + rpl_parallel_thread *thr; + }; + /* + A struct to keep track of into which "generation" an XA XID was last + scheduled. A "generation" means that we know that every worker thread + slot in the rpl_parallel_entry was scheduled at least once. When more + that two generations have passed, we can safely reuse the XID in a + different worker. + */ + struct xid_active_generation { + uint64 generation; + sched_bucket *thr; + xid_t xid; + }; + mysql_mutex_t LOCK_parallel_entry; mysql_cond_t COND_parallel_entry; uint32 domain_id; @@ -374,17 +395,36 @@ struct rpl_parallel_entry { uint64 stop_sub_id; /* - Cyclic array recording the last rpl_thread_max worker threads that we + Array recording the last rpl_thread_max worker threads that we queued event for. This is used to limit how many workers a single domain can occupy (--slave-domain-parallel-threads). + The array is structured as a FIFO using an I_List thread_sched_fifo. + Note that workers are never explicitly deleted from the array. Instead, we need to check (under LOCK_rpl_thread) that the thread still belongs to us before re-using (rpl_thread::current_owner). */ - rpl_parallel_thread **rpl_threads; + sched_bucket *rpl_threads; + I_List *thread_sched_fifo; uint32 rpl_thread_max; - uint32 rpl_thread_idx; + /* + Keep track of all XA XIDs that may still be active in a worker thread. + The elements are of type xid_active_generation. + */ + DYNAMIC_ARRAY maybe_active_xid; + /* + Keeping track of the current scheduling generation. + + A new generation means that every worker thread in the rpl_threads array + have been scheduled at least one event group. + + When we have scheduled to slot current_generation_idx= 0, 1, ..., N-1 in this + order, we know that (at least) one generation has passed. + */ + uint64 current_generation; + uint32 current_generation_idx; + /* The sub_id of the last transaction to commit within this domain_id. Must be accessed under LOCK_parallel_entry protection. @@ -440,14 +480,22 @@ struct rpl_parallel_entry { /* Relay log info of replication source for this entry. */ Relay_log_info *rli; + void check_scheduling_generation(sched_bucket *cur); + sched_bucket *check_xa_xid_dependency(xid_t *xid); rpl_parallel_thread * choose_thread(rpl_group_info *rgi, bool *did_enter_cond, PSI_stage_info *old_stage, Gtid_log_event *gtid_ev); rpl_parallel_thread * - choose_thread_internal(uint idx, bool *did_enter_cond, rpl_group_info *rgi, - PSI_stage_info *old_stage); + choose_thread_internal(sched_bucket *cur_thr, bool *did_enter_cond, + rpl_group_info *rgi, PSI_stage_info *old_stage); int queue_master_restart(rpl_group_info *rgi, Format_description_log_event *fdev); + /* + the initial size of maybe_ array corresponds to the case of + each worker receives perhaps unlikely XA-PREPARE and XA-COMMIT within + the same generation. + */ + inline uint active_xid_init_alloc() { return 3 * 2 * rpl_thread_max; } }; struct rpl_parallel { HASH domain_hash; diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 68f424943c5..a8503650ab7 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -2262,7 +2262,7 @@ delete_or_keep_event_post_apply(rpl_group_info *rgi, } -void rpl_group_info::cleanup_context(THD *thd, bool error) +void rpl_group_info::cleanup_context(THD *thd, bool error, bool keep_domain_owner) { DBUG_ENTER("rpl_group_info::cleanup_context"); DBUG_PRINT("enter", ("error: %d", (int) error)); @@ -2317,7 +2317,7 @@ void rpl_group_info::cleanup_context(THD *thd, bool error) Ensure we always release the domain for others to process, when using --gtid-ignore-duplicates. */ - if (gtid_ignore_duplicate_state != GTID_DUPLICATE_NULL) + if (gtid_ignore_duplicate_state != GTID_DUPLICATE_NULL && !keep_domain_owner) rpl_global_gtid_slave_state->release_domain_owner(this); } diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h index 30e1bb45ec4..8d4688c0794 100644 --- a/sql/rpl_rli.h +++ b/sql/rpl_rli.h @@ -564,6 +564,10 @@ private: Guarded by data_lock. Written by the sql thread. Read by client threads executing SHOW SLAVE STATUS. + + This is calculated as: + clock_time_for_event_on_master + clock_difference_between_master_and_slave + + SQL_DELAY. */ time_t sql_delay_end; @@ -959,7 +963,7 @@ struct rpl_group_info } void clear_tables_to_lock(); - void cleanup_context(THD *, bool); + void cleanup_context(THD *, bool, bool keep_domain_owner= false); void slave_close_thread_tables(THD *); void mark_start_commit_no_lock(); void mark_start_commit(); diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 34794d03e6c..0a570892e96 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -10673,7 +10673,7 @@ ER_UNKNOWN_DATA_TYPE eng "Unknown data type: '%-.64s'" spa "Tipo de datos desconocido: '%-.64s'" ER_UNKNOWN_OPERATOR - eng "Operator does not exists: '%-.128s'" + eng "Operator does not exist: '%-.128s'" spa "El operador no existe: '%-.128s'" ER_UNUSED_29 eng "You should never see it" diff --git a/sql/slave.cc b/sql/slave.cc index 8e1747e1e24..bd39cf51759 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -4423,6 +4423,13 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, rli->last_inuse_relaylog->dequeued_count))) && event_can_update_last_master_timestamp(ev)) { + /* + This is the first event from the master after the slave was up to date + and has been waiting for new events. + We update last_master_timestamp before executing the event to not + have Seconds_after_master == 0 while executing the event. + last_master_timestamp will be updated again when the event is commited. + */ if (rli->last_master_timestamp < ev->when) { rli->last_master_timestamp= ev->when; @@ -4459,7 +4466,7 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, Seconds_Behind_Master is zero. */ if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT && - rli->last_master_timestamp < ev->when) + rli->last_master_timestamp < ev->when + (time_t) ev->exec_time) rli->last_master_timestamp= ev->when + (time_t) ev->exec_time; DBUG_ASSERT(rli->last_master_timestamp >= 0); @@ -7600,9 +7607,6 @@ static int connect_to_master(THD* thd, MYSQL* mysql, Master_info* mi, default_client_charset_info->cs_name.str); } - /* This one is not strictly needed but we have it here for completeness */ - mysql_options(mysql, MYSQL_SET_CHARSET_DIR, (char *) charsets_dir); - /* Set MYSQL_PLUGIN_DIR in case master asks for an external authentication plugin */ if (opt_plugin_dir_ptr && *opt_plugin_dir_ptr) mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir_ptr); @@ -7746,8 +7750,6 @@ MYSQL *rpl_connect_master(MYSQL *mysql) mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset_info->cs_name.str); - /* This one is not strictly needed but we have it here for completeness */ - mysql_options(mysql, MYSQL_SET_CHARSET_DIR, (char *) charsets_dir); if (mi->user == NULL || mi->user[0] == 0 diff --git a/sql/sp.cc b/sql/sp.cc index 3235343586d..4f82b983755 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1944,7 +1944,7 @@ Sp_handler::sp_show_create_routine(THD *thd, DBUG_EXECUTE_IF("cache_sp_in_show_create", /* Some tests need just need a way to cache SP without other side-effects.*/ - sp_cache_routine(thd, name, false, &sp); + sp_cache_routine(thd, name, &sp); sp->show_create_routine(thd, this); DBUG_RETURN(false); ); @@ -2368,7 +2368,7 @@ Sp_handler::sp_cache_routine_reentrant(THD *thd, int ret; Parser_state *oldps= thd->m_parser_state; thd->m_parser_state= NULL; - ret= sp_cache_routine(thd, name, false, sp); + ret= sp_cache_routine(thd, name, sp); thd->m_parser_state= oldps; return ret; } @@ -2775,7 +2775,6 @@ void sp_update_stmt_used_routines(THD *thd, Query_tables_list *prelocking_ctx, */ int Sroutine_hash_entry::sp_cache_routine(THD *thd, - bool lookup_only, sp_head **sp) const { char qname_buff[NAME_LEN*2+1+1]; @@ -2788,7 +2787,7 @@ int Sroutine_hash_entry::sp_cache_routine(THD *thd, */ DBUG_ASSERT(mdl_request.ticket || this == thd->lex->sroutines_list.first); - return m_handler->sp_cache_routine(thd, &name, lookup_only, sp); + return m_handler->sp_cache_routine(thd, &name, sp); } @@ -2800,9 +2799,6 @@ int Sroutine_hash_entry::sp_cache_routine(THD *thd, @param[in] thd Thread context. @param[in] name Name of routine. - @param[in] lookup_only Only check that the routine is in the cache. - If it's not, don't try to load. If it is present, - but old, don't try to reload. @param[out] sp Pointer to sp_head object for routine, NULL if routine was not found. @@ -2813,7 +2809,6 @@ int Sroutine_hash_entry::sp_cache_routine(THD *thd, int Sp_handler::sp_cache_routine(THD *thd, const Database_qualified_name *name, - bool lookup_only, sp_head **sp) const { int ret= 0; @@ -2825,9 +2820,6 @@ int Sp_handler::sp_cache_routine(THD *thd, *sp= sp_cache_lookup(spc, name); - if (lookup_only) - DBUG_RETURN(SP_OK); - if (*sp) { sp_cache_flush_obsolete(spc, sp); @@ -2879,7 +2871,6 @@ int Sp_handler::sp_cache_routine(THD *thd, * name->m_db is a database name, e.g. "dbname" * name->m_name is a package-qualified name, e.g. "pkgname.spname" - @param lookup_only - don't load mysql.proc if not cached @param [OUT] sp - the result is returned here. @retval false - loaded or does not exists @retval true - error while loading mysql.proc @@ -2889,14 +2880,13 @@ int Sp_handler::sp_cache_package_routine(THD *thd, const LEX_CSTRING &pkgname_cstr, const Database_qualified_name *name, - bool lookup_only, sp_head **sp) const + sp_head **sp) const { DBUG_ENTER("sp_cache_package_routine"); DBUG_ASSERT(type() == SP_TYPE_FUNCTION || type() == SP_TYPE_PROCEDURE); sp_name pkgname(&name->m_db, &pkgname_cstr, false); sp_head *ph= NULL; int ret= sp_handler_package_body.sp_cache_routine(thd, &pkgname, - lookup_only, &ph); if (!ret) { @@ -2931,12 +2921,12 @@ Sp_handler::sp_cache_package_routine(THD *thd, int Sp_handler::sp_cache_package_routine(THD *thd, const Database_qualified_name *name, - bool lookup_only, sp_head **sp) const + sp_head **sp) const { DBUG_ENTER("Sp_handler::sp_cache_package_routine"); Prefix_name_buf pkgname(thd, name->m_name); DBUG_ASSERT(pkgname.length); - DBUG_RETURN(sp_cache_package_routine(thd, pkgname, name, lookup_only, sp)); + DBUG_RETURN(sp_cache_package_routine(thd, pkgname, name, sp)); } diff --git a/sql/sp.h b/sql/sp.h index c73ff2877b0..698b576e40e 100644 --- a/sql/sp.h +++ b/sql/sp.h @@ -102,10 +102,10 @@ protected: int sp_cache_package_routine(THD *thd, const LEX_CSTRING &pkgname_cstr, const Database_qualified_name *name, - bool lookup_only, sp_head **sp) const; + sp_head **sp) const; int sp_cache_package_routine(THD *thd, const Database_qualified_name *name, - bool lookup_only, sp_head **sp) const; + sp_head **sp) const; sp_head *sp_find_package_routine(THD *thd, const LEX_CSTRING pkgname_str, const Database_qualified_name *name, @@ -202,7 +202,7 @@ public: const Database_qualified_name *name, bool cache_only) const; virtual int sp_cache_routine(THD *thd, const Database_qualified_name *name, - bool lookup_only, sp_head **sp) const; + sp_head **sp) const; int sp_cache_routine_reentrant(THD *thd, const Database_qualified_name *nm, @@ -283,9 +283,9 @@ class Sp_handler_package_procedure: public Sp_handler_procedure { public: int sp_cache_routine(THD *thd, const Database_qualified_name *name, - bool lookup_only, sp_head **sp) const + sp_head **sp) const { - return sp_cache_package_routine(thd, name, lookup_only, sp); + return sp_cache_package_routine(thd, name, sp); } sp_head *sp_find_routine(THD *thd, const Database_qualified_name *name, @@ -332,9 +332,9 @@ class Sp_handler_package_function: public Sp_handler_function { public: int sp_cache_routine(THD *thd, const Database_qualified_name *name, - bool lookup_only, sp_head **sp) const + sp_head **sp) const { - return sp_cache_package_routine(thd, name, lookup_only, sp); + return sp_cache_package_routine(thd, name, sp); } sp_head *sp_find_routine(THD *thd, const Database_qualified_name *name, @@ -632,7 +632,7 @@ public: const Sp_handler *m_handler; - int sp_cache_routine(THD *thd, bool lookup_only, sp_head **sp) const; + int sp_cache_routine(THD *thd, sp_head **sp) const; }; diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc index 1da807e9d59..f67ef4218af 100644 --- a/sql/sp_cache.cc +++ b/sql/sp_cache.cc @@ -78,6 +78,8 @@ private: /* All routines in this cache */ HASH m_hashtable; +public: + void clear(); }; // class sp_cache #ifdef HAVE_PSI_INTERFACE @@ -313,6 +315,10 @@ sp_cache::cleanup() my_hash_free(&m_hashtable); } +void sp_cache::clear() +{ + my_hash_reset(&m_hashtable); +} void Sp_caches::sp_caches_clear() { @@ -321,3 +327,15 @@ void Sp_caches::sp_caches_clear() sp_cache_clear(&sp_package_spec_cache); sp_cache_clear(&sp_package_body_cache); } + +void Sp_caches::sp_caches_empty() +{ + if (sp_proc_cache) + sp_proc_cache->clear(); + if (sp_func_cache) + sp_func_cache->clear(); + if (sp_package_spec_cache) + sp_package_spec_cache->clear(); + if (sp_package_body_cache) + sp_package_body_cache->clear(); +} diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 58235055d7e..b7a9ba4c80d 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -3862,6 +3862,9 @@ sp_instr_stmt::execute(THD *thd, uint *nextp) thd->update_stats(); thd->lex->sql_command= save_sql_command; *nextp= m_ip+1; +#ifdef PROTECT_STATEMENT_MEMROOT + mark_as_qc_used(); +#endif } thd->set_query(query_backup); thd->query_name_consts= 0; diff --git a/sql/sp_head.h b/sql/sp_head.h index da4e5763a48..b418ef25386 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -1138,7 +1138,7 @@ public: sp_instr(uint ip, sp_pcontext *ctx) :Query_arena(0, STMT_INITIALIZED_FOR_SP), marked(0), m_ip(ip), m_ctx(ctx) #ifdef PROTECT_STATEMENT_MEMROOT - , m_has_been_run(false) + , m_has_been_run(NON_RUN) #endif {} @@ -1233,21 +1233,29 @@ public: #ifdef PROTECT_STATEMENT_MEMROOT bool has_been_run() const { - return m_has_been_run; + return m_has_been_run == RUN; + } + + void mark_as_qc_used() + { + m_has_been_run= QC; } void mark_as_run() { - m_has_been_run= true; + if (m_has_been_run == QC) + m_has_been_run= NON_RUN; // answer was from WC => not really executed + else + m_has_been_run= RUN; } void mark_as_not_run() { - m_has_been_run= false; + m_has_been_run= NON_RUN; } private: - bool m_has_been_run; + enum {NON_RUN, QC, RUN} m_has_been_run; #endif }; // class sp_instr : public Sql_alloc diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 9e446d09a35..c593035f227 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3780,7 +3780,7 @@ open_and_process_routine(THD *thd, Query_tables_list *prelocking_ctx, DBUG_RETURN(TRUE); /* Ensures the routine is up-to-date and cached, if exists. */ - if (rt->sp_cache_routine(thd, has_prelocking_list, &sp)) + if (rt->sp_cache_routine(thd, &sp)) DBUG_RETURN(TRUE); /* Remember the version of the routine in the parse tree. */ @@ -3821,7 +3821,7 @@ open_and_process_routine(THD *thd, Query_tables_list *prelocking_ctx, Validating routine version is unnecessary, since CALL does not affect the prepared statement prelocked list. */ - if (rt->sp_cache_routine(thd, false, &sp)) + if (rt->sp_cache_routine(thd, &sp)) DBUG_RETURN(TRUE); } } @@ -5852,13 +5852,23 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count, uint flags) } } - DEBUG_SYNC(thd, "before_lock_tables_takes_lock"); +#ifdef ENABLED_DEBUG_SYNC + if (!tables || + !(strcmp(tables->db.str, "mysql") == 0 && + strcmp(tables->table_name.str, "proc") == 0)) + DEBUG_SYNC(thd, "before_lock_tables_takes_lock"); +#endif if (! (thd->lock= mysql_lock_tables(thd, start, (uint) (ptr - start), flags))) DBUG_RETURN(TRUE); - DEBUG_SYNC(thd, "after_lock_tables_takes_lock"); +#ifdef ENABLED_DEBUG_SYNC + if (!tables || + !(strcmp(tables->db.str, "mysql") == 0 && + strcmp(tables->table_name.str, "proc") == 0)) + DEBUG_SYNC(thd, "after_lock_tables_takes_lock"); +#endif if (thd->lex->requires_prelocking() && thd->lex->sql_command != SQLCOM_LOCK_TABLES && diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index b284189db23..34d063fcca0 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -2530,14 +2530,9 @@ void Query_cache::destroy() void Query_cache::disable_query_cache(THD *thd) { + lock(thd); m_cache_status= DISABLE_REQUEST; - /* - If there is no requests in progress try to free buffer. - try_lock(TRY) will exit immediately if there is lock. - unlock() should free block. - */ - if (m_requests_in_progress == 0 && !try_lock(thd, TRY)) - unlock(); + unlock(); } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 61eb1468108..0d39f359a09 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -893,6 +893,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier) prepare_derived_at_open= FALSE; create_tmp_table_for_derived= FALSE; save_prep_leaf_list= FALSE; + reset_sp_cache= false; org_charset= 0; /* Restore THR_THD */ set_current_thd(old_THR_THD); @@ -8333,6 +8334,34 @@ wait_for_commit::unregister_wait_for_prior_commit2() mysql_mutex_unlock(&LOCK_wait_commit); } +/* + Wait # seconds or until someone sends a signal (through kill) + + Note that this must have same prototype as my_sleep_for_space() +*/ + +C_MODE_START + +void mariadb_sleep_for_space(unsigned int seconds) +{ + THD *thd= current_thd; + PSI_stage_info old_stage; + if (!thd) + { + sleep(seconds); + return; + } + mysql_mutex_lock(&thd->LOCK_wakeup_ready); + thd->ENTER_COND(&thd->COND_wakeup_ready, &thd->LOCK_wakeup_ready, + &stage_waiting_for_disk_space, &old_stage); + if (!thd->killed) + mysql_cond_wait(&thd->COND_wakeup_ready, &thd->LOCK_wakeup_ready); + thd->EXIT_COND(&old_stage); + return; +} + +C_MODE_END + bool Discrete_intervals_list::append(ulonglong start, ulonglong val, ulonglong incr) diff --git a/sql/sql_class.h b/sql/sql_class.h index cea0b8543c6..9cca3c170c1 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1,5 +1,4 @@ /* - Copyright (c) 2000, 2016, Oracle and/or its affiliates. Copyright (c) 2009, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify @@ -2470,6 +2469,11 @@ public: swap_variables(sp_cache*, sp_package_body_cache, rhs.sp_package_body_cache); } void sp_caches_clear(); + /** + Clear content of sp related caches. + Don't delete cache objects itself. + */ + void sp_caches_empty(); }; @@ -2960,6 +2964,12 @@ public: bool save_prep_leaf_list; + /** + The data member reset_sp_cache is to signal that content of sp_cache + must be reset (all items be removed from it). + */ + bool reset_sp_cache; + /* container for handler's private per-connection data */ Ha_data ha_data[MAX_HA]; @@ -4834,24 +4844,24 @@ public: */ bool copy_db_to(LEX_CSTRING *to) { - if (db.str == NULL) + if (db.str) { - /* - No default database is set. In this case if it's guaranteed that - no CTE can be used in the statement then we can throw an error right - now at the parser stage. Otherwise the decision about throwing such - a message must be postponed until a post-parser stage when we are able - to resolve all CTE names as we don't need this message to be thrown - for any CTE references. - */ - if (!lex->with_cte_resolution) - my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); - return TRUE; + to->str= strmake(db.str, db.length); + to->length= db.length; + return to->str == NULL; /* True on error */ } - to->str= strmake(db.str, db.length); - to->length= db.length; - return to->str == NULL; /* True on error */ + /* + No default database is set. In this case if it's guaranteed that + no CTE can be used in the statement then we can throw an error right + now at the parser stage. Otherwise the decision about throwing such + a message must be postponed until a post-parser stage when we are able + to resolve all CTE names as we don't need this message to be thrown + for any CTE references. + */ + if (!lex->with_cte_resolution) + my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); + return TRUE; } /* Get db name or "". Use for printing current db */ const char *get_db() @@ -8199,6 +8209,10 @@ extern THD_list server_threads; void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps, uint field_count); +C_MODE_START +void mariadb_sleep_for_space(unsigned int seconds); +C_MODE_END + #ifdef WITH_WSREP extern void wsrep_to_isolation_end(THD*); #endif diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index f8ac6516a00..2ee6317123b 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -1590,6 +1590,7 @@ bool JOIN_CACHE::put_record() { bool is_full; uchar *link= 0; + DBUG_ASSERT(!for_explain_only); if (prev_cache) link= prev_cache->get_curr_rec_link(); write_record_data(link, &is_full); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index e6db1456a0c..3823262233f 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -4264,17 +4264,18 @@ uint8 LEX::get_effective_with_check(TABLE_LIST *view) bool LEX::copy_db_to(LEX_CSTRING *to) { - if (sphead && sphead->m_name.str) - { - DBUG_ASSERT(sphead->m_db.str && sphead->m_db.length); - /* - It is safe to assign the string by-pointer, both sphead and - its statements reside in the same memory root. - */ - *to= sphead->m_db; - return FALSE; - } - return thd->copy_db_to(to); + if (!sphead || !sphead->m_name.str) + return thd->copy_db_to(to); + + DBUG_ASSERT(sphead->m_db.str); + DBUG_ASSERT(sphead->m_db.length); + + /* + It is safe to assign the string by-pointer, both sphead and + its statements reside in the same memory root. + */ + *to= sphead->m_db; + return FALSE; } /** diff --git a/sql/sql_manager.cc b/sql/sql_manager.cc index 5cd66d8047a..b3d95c9ed31 100644 --- a/sql/sql_manager.cc +++ b/sql/sql_manager.cc @@ -26,7 +26,11 @@ #include "sql_manager.h" #include "sql_base.h" // flush_tables -static bool volatile manager_thread_in_use = 0; +/* + Values for manager_thread_in_use: 0 means "not started". 1 means "started + and active". 2 means "stopped". +*/ +static int volatile manager_thread_in_use = 0; static bool abort_manager = false; pthread_t manager_thread; @@ -44,7 +48,7 @@ static struct handler_cb *cb_list; // protected by LOCK_manager bool mysql_manager_submit(void (*action)(void *), void *data) { bool result= FALSE; - DBUG_ASSERT(manager_thread_in_use); + DBUG_ASSERT(manager_thread_in_use == 1); struct handler_cb **cb; mysql_mutex_lock(&LOCK_manager); cb= &cb_list; @@ -119,7 +123,7 @@ pthread_handler_t handle_manager(void *arg __attribute__((unused))) mysql_mutex_lock(&LOCK_manager); } DBUG_ASSERT(cb_list == NULL); - manager_thread_in_use = 0; + manager_thread_in_use = 2; mysql_mutex_unlock(&LOCK_manager); mysql_mutex_destroy(&LOCK_manager); mysql_cond_destroy(&COND_manager); @@ -148,6 +152,15 @@ void start_handle_manager() } mysql_mutex_lock(&LOCK_manager); + /* + Wait for manager thread to have started, otherwise in extreme cases the + server may start up and have initiated shutdown at the time the manager + thread even starts to run. + + Allow both values 1 and 2 for manager_thread_in_use, so that we will not + get stuck here if the manager thread somehow manages to start up and + abort again before we have time to test it here. + */ while (!manager_thread_in_use) mysql_cond_wait(&COND_manager, &LOCK_manager); mysql_mutex_unlock(&LOCK_manager); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 382a5d942f8..339fea26fc1 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2250,6 +2250,7 @@ dispatch_command_return dispatch_command(enum enum_server_command command, THD * my_eof(thd); kill_mysql(thd); error=TRUE; + DBUG_EXECUTE_IF("simulate_slow_client_at_shutdown", my_sleep(2000000);); break; } #endif @@ -2407,6 +2408,11 @@ resume: } #endif /* WITH_WSREP */ + if (thd->reset_sp_cache) + { + thd->sp_caches_empty(); + thd->reset_sp_cache= false; + } if (do_end_of_statement) { @@ -2483,6 +2489,7 @@ resume: MYSQL_COMMAND_DONE(res); } DEBUG_SYNC(thd,"dispatch_command_end"); + DEBUG_SYNC(thd,"dispatch_command_end2"); /* Check that some variables are reset properly */ DBUG_ASSERT(thd->abort_on_warning == 0); @@ -5890,7 +5897,7 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt) if (sph->sp_resolve_package_routine(thd, thd->lex->sphead, lex->spname, &sph, &pkgname)) return true; - if (sph->sp_cache_routine(thd, lex->spname, false, &sp)) + if (sph->sp_cache_routine(thd, lex->spname, &sp)) goto error; if (!sp || sp->show_routine_code(thd)) { @@ -8263,10 +8270,6 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, List *partition_names, LEX_STRING *option) { - TABLE_LIST *ptr; - TABLE_LIST *UNINIT_VAR(previous_table_ref); /* The table preceding the current one. */ - LEX_CSTRING alias_str; - LEX *lex= thd->lex; DBUG_ENTER("add_table_to_list"); DBUG_PRINT("enter", ("Table '%s' (%p) Select %p (%u)", (alias ? alias->str : table->table.str), @@ -8276,9 +8279,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, if (unlikely(!table)) DBUG_RETURN(0); // End of memory - alias_str= alias ? *alias : table->table; - DBUG_ASSERT(alias_str.str); - if (!MY_TEST(table_options & TL_OPTION_ALIAS) && + if (!(table_options & TL_OPTION_ALIAS) && unlikely(check_table_name(table->table.str, table->table.length, FALSE))) { my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str); @@ -8293,6 +8294,34 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, DBUG_RETURN(0); } + LEX_CSTRING db{0, 0}; + bool fqtn= false; + LEX *lex= thd->lex; + if (table->db.str) + { + fqtn= TRUE; + db= table->db; + } + else if (!lex->with_cte_resolution && lex->copy_db_to(&db)) + DBUG_RETURN(0); + else + fqtn= FALSE; + bool info_schema= is_infoschema_db(&db); + if (!table->sel && info_schema && + (table_options & TL_OPTION_UPDATING) && + /* Special cases which are processed by commands itself */ + lex->sql_command != SQLCOM_CHECK && + lex->sql_command != SQLCOM_CHECKSUM) + { + my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), + thd->security_ctx->priv_user, + thd->security_ctx->priv_host, + INFORMATION_SCHEMA_NAME.str); + DBUG_RETURN(0); + } + + LEX_CSTRING alias_str= alias ? *alias : table->table; + DBUG_ASSERT(alias_str.str); if (!alias) /* Alias is case sensitive */ { if (unlikely(table->sel)) @@ -8305,65 +8334,15 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, if (unlikely(!(alias_str.str= (char*) thd->memdup(alias_str.str, alias_str.length+1)))) DBUG_RETURN(0); } - if (unlikely(!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))) - DBUG_RETURN(0); /* purecov: inspected */ - if (table->db.str) - { - ptr->is_fqtn= TRUE; - ptr->db= table->db; - } - else if (!lex->with_cte_resolution && lex->copy_db_to(&ptr->db)) - DBUG_RETURN(0); - else - ptr->is_fqtn= FALSE; - ptr->alias= alias_str; - ptr->is_alias= alias ? TRUE : FALSE; - if (lower_case_table_names) - { - if (table->table.length) - table->table.length= my_casedn_str(files_charset_info, - (char*) table->table.str); - if (ptr->db.length && ptr->db.str != any_db.str) - ptr->db.length= my_casedn_str(files_charset_info, (char*) ptr->db.str); - } + bool has_alias_ptr= alias != nullptr; + void *memregion= thd->calloc(sizeof(TABLE_LIST)); + TABLE_LIST *ptr= new (memregion) TABLE_LIST(thd, db, fqtn, alias_str, + has_alias_ptr, table, lock_type, + mdl_type, table_options, + info_schema, this, + index_hints_arg, option); - ptr->table_name= table->table; - ptr->lock_type= lock_type; - ptr->mdl_type= mdl_type; - ptr->table_options= table_options; - ptr->updating= MY_TEST(table_options & TL_OPTION_UPDATING); - /* TODO: remove TL_OPTION_FORCE_INDEX as it looks like it's not used */ - ptr->force_index= MY_TEST(table_options & TL_OPTION_FORCE_INDEX); - ptr->ignore_leaves= MY_TEST(table_options & TL_OPTION_IGNORE_LEAVES); - ptr->sequence= MY_TEST(table_options & TL_OPTION_SEQUENCE); - ptr->derived= table->sel; - if (!ptr->derived && is_infoschema_db(&ptr->db)) - { - if (ptr->updating && - /* Special cases which are processed by commands itself */ - lex->sql_command != SQLCOM_CHECK && - lex->sql_command != SQLCOM_CHECKSUM) - { - my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), - thd->security_ctx->priv_user, - thd->security_ctx->priv_host, - INFORMATION_SCHEMA_NAME.str); - DBUG_RETURN(0); - } - ST_SCHEMA_TABLE *schema_table; - schema_table= find_schema_table(thd, &ptr->table_name); - ptr->schema_table_name= ptr->table_name; - ptr->schema_table= schema_table; - } - ptr->select_lex= this; - /* - We can't cache internal temporary tables between prepares as the - table may be deleted before next exection. - */ - ptr->cacheable_table= !table->is_derived_table(); - ptr->index_hints= index_hints_arg; - ptr->option= option ? option->str : 0; /* check that used name is unique. Sequences are ignored */ if (lock_type != TL_IGNORE && !ptr->sequence) { @@ -8386,6 +8365,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, } } /* Store the table reference preceding the current one. */ + TABLE_LIST *UNINIT_VAR(previous_table_ref); /* The table preceding the current one. */ if (table_list.elements > 0 && likely(!ptr->sequence)) { /* diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 23a0f492760..f4ce4a4d6bb 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -4262,7 +4262,7 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, if (unlikely(error)) { - sql_print_error("Parsing options for plugin '%s' failed.", + sql_print_error("Parsing options for plugin '%s' failed. Disabling plugin", tmp->name.str); goto err; } diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc index 8f0f15a982a..c81d749fad4 100644 --- a/sql/sql_reload.cc +++ b/sql/sql_reload.cc @@ -68,6 +68,15 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options, bool result=0; select_errors=0; /* Write if more errors */ int tmp_write_to_binlog= *write_to_binlog= 1; +#ifndef DBUG_OFF + /* + When invoked for handling a SIGHUP by rpl_shutdown_sighup.test, we need to + force the signal handler to wait after REFRESH_TABLES, as that will check + for a killed server, and we need to call hostname_cache_refresh after + server cleanup has happened to trigger MDEV-30260. + */ + int do_dbug_sleep= 0; +#endif DBUG_ASSERT(!thd || !thd->in_sub_stmt); @@ -100,6 +109,15 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options, */ my_error(ER_UNKNOWN_ERROR, MYF(0)); } + +#ifndef DBUG_OFF + DBUG_EXECUTE_IF("hold_sighup_log_refresh", { + DBUG_ASSERT(!debug_sync_set_action( + thd, STRING_WITH_LEN("now SIGNAL in_reload_acl_and_cache " + "WAIT_FOR refresh_logs"))); + do_dbug_sleep= 1; + }); +#endif } opt_noacl= 0; @@ -352,6 +370,11 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options, } my_dbopt_cleanup(); } + +#ifndef DBUG_OFF + if (do_dbug_sleep) + my_sleep(3000000); // 3s +#endif if (options & REFRESH_HOSTS) hostname_cache_refresh(); if (thd && (options & REFRESH_STATUS)) diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index c2d1776f241..114c36a5eac 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -221,7 +221,7 @@ static int fake_rotate_event(binlog_send_info *info, ulonglong position, char* p = info->log_file_name+dirname_length(info->log_file_name); uint ident_len = (uint) strlen(p); String *packet= info->packet; - ha_checksum crc; + ha_checksum crc= 0; /* reset transmit packet for the fake rotate event below */ if (reset_transmit_packet(info, info->flags, &ev_offset, &info->errmsg)) @@ -262,7 +262,7 @@ static int fake_gtid_list_event(binlog_send_info *info, { my_bool do_checksum; int err; - ha_checksum crc; + ha_checksum crc= 0; char buf[128]; String str(buf, sizeof(buf), system_charset_info); String* packet= info->packet; @@ -2828,12 +2828,6 @@ static int send_one_binlog_file(binlog_send_info *info, */ if (send_events(info, log, linfo, end_pos)) return 1; - DBUG_EXECUTE_IF("Notify_binlog_EOF", - { - const char act[]= "now signal eof_reached"; - DBUG_ASSERT(!debug_sync_set_action(current_thd, - STRING_WITH_LEN(act))); - };); } return 1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 01d0d2c7f1e..0994ddb75f2 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3596,7 +3596,7 @@ bool JOIN::make_aggr_tables_info() distinct in the engine, so we do this for all queries, not only GROUP BY queries. */ - if (tables_list && top_join_tab_count && !procedure) + if (tables_list && top_join_tab_count && !only_const_tables() && !procedure) { /* At the moment we only support push down for queries where @@ -31910,7 +31910,26 @@ void JOIN::init_join_cache_and_keyread() if (!(table->file->index_flags(table->file->keyread, 0, 1) & HA_CLUSTERED_INDEX)) table->mark_index_columns(table->file->keyread, table->read_set); } - if (tab->cache && tab->cache->init(select_options & SELECT_DESCRIBE)) + bool init_for_explain= false; + + /* + Can we use lightweight initalization mode just for EXPLAINs? We can if + we're certain that the optimizer will not execute the subquery. + The optimzier will not execute the subquery if it's too expensive. For + the exact criteria, see Item_subselect::is_expensive(). + Note that the subquery might be a UNION and we might not yet know if it + is expensive. + What we do know is that if this SELECT is too expensive, then the whole + subquery will be too expensive as well. + So, we can use lightweight initialization (init_for_explain=true) if this + SELECT examines more than @@expensive_subquery_limit rows. + */ + if ((select_options & SELECT_DESCRIBE) && + get_examined_rows() >= thd->variables.expensive_subquery_limit) + { + init_for_explain= true; + } + if (tab->cache && tab->cache->init(init_for_explain)) revise_cache_usage(tab); else tab->remove_redundant_bnl_scan_conds(); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 3eb7012677e..2d79ee1fd02 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1468,6 +1468,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, temporary_table_was_dropped= 1; } is_temporary= 1; + thd->reset_sp_cache= true; } if ((drop_temporary && if_exists) || temporary_table_was_dropped) @@ -1841,8 +1842,11 @@ report_error: } DBUG_PRINT("table", ("table: %p s: %p", table->table, table->table ? table->table->s : NULL)); + if (is_temporary_table(table)) + thd->reset_sp_cache= true; } DEBUG_SYNC(thd, "rm_table_no_locks_before_binlog"); + thd->used|= THD::THREAD_SPECIFIC_USED; error= 0; @@ -4678,6 +4682,7 @@ int create_table_impl(THD *thd, if (is_trans != NULL) *is_trans= table->file->has_transactions(); + thd->reset_sp_cache= true; thd->used|= THD::THREAD_SPECIFIC_USED; create_info->table= table; // Store pointer to table } @@ -5166,7 +5171,8 @@ static bool make_unique_constraint_name(THD *thd, LEX_CSTRING *name, if (!check) // Found unique name { name->length= (size_t) (real_end - buff); - name->str= strmake_root(thd->stmt_arena->mem_root, buff, name->length); + name->str= thd->strmake(buff, name->length); + return (name->str == NULL); } } @@ -10252,14 +10258,14 @@ 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, used_engine)) + wsrep_check_sequence(thd, create_info->seq_create_info, used_engine)) DBUG_RETURN(TRUE); - if (WSREP(thd) && + if (WSREP(thd) && table && (thd->lex->sql_command == SQLCOM_ALTER_TABLE || thd->lex->sql_command == SQLCOM_CREATE_INDEX || thd->lex->sql_command == SQLCOM_DROP_INDEX) && - !wsrep_should_replicate_ddl(thd, table_list->table->s->db_type())) + !wsrep_should_replicate_ddl(thd, table->s->db_type())) DBUG_RETURN(true); #endif /* WITH_WSREP */ @@ -12731,12 +12737,10 @@ bool Sql_cmd_create_table_like::execute(THD *thd) wsrep_check_sequence(thd, lex->create_info.seq_create_info, used_engine)) DBUG_RETURN(true); - WSREP_TO_ISOLATION_BEGIN_ALTER(create_table->db.str, - create_table->table_name.str, - first_table, &alter_info, NULL, - &create_info) - { - WSREP_WARN("CREATE TABLE isolation failure"); + WSREP_TO_ISOLATION_BEGIN_ALTER(create_table->db.str, create_table->table_name.str, + first_table, &alter_info, NULL, &create_info) + { + WSREP_WARN("CREATE TABLE isolation failure"); res= true; goto end_with_restore_list; } diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 9d59b7c35a8..65cddab89f8 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -1265,26 +1265,21 @@ bool st_select_lex_unit::join_union_item_types(THD *thd_arg, } -bool init_item_int(THD* thd, Item_int* &item) +static bool init_item_int(THD* thd, Item_int* &item) { if (!item) { - Query_arena *arena, backup_arena; - arena= thd->activate_stmt_arena_if_needed(&backup_arena); - item= new (thd->mem_root) Item_int(thd, 0); - if (arena) - thd->restore_active_arena(arena, &backup_arena); - if (!item) - return false; + return true; } else { item->value= 0; } - return true; + + return false; } @@ -1760,8 +1755,12 @@ cont: for(uint i= 0; i< hidden; i++) { - init_item_int(thd, addon_fields[i]); - types.push_front(addon_fields[i]); + if (init_item_int(thd, addon_fields[i]) || + types.push_front(addon_fields[i])) + { + types.empty(); + goto err; + } addon_fields[i]->name.str= i ? "__CNT_1" : "__CNT_2"; addon_fields[i]->name.length= 7; } diff --git a/sql/sys_vars.inl b/sql/sys_vars.inl index 2fd6d04297e..932b12fcb2e 100644 --- a/sql/sys_vars.inl +++ b/sql/sys_vars.inl @@ -947,21 +947,10 @@ public: { option.var_type|= GET_STR; } bool do_check(THD *thd, set_var *var) { - char buff[STRING_BUFFER_USUAL_SIZE]; - String str(buff, sizeof(buff), system_charset_info), *res; - - if (!(res=var->value->val_str(&str))) - { + bool rc= Sys_var_charptr::do_string_check(thd, var, charset(thd)); + if (var->save_result.string_value.str == nullptr) var->save_result.string_value.str= const_cast(""); - var->save_result.string_value.length= 0; - } - else - { - size_t len= res->length(); - var->save_result.string_value.str= thd->strmake(res->ptr(), len); - var->save_result.string_value.length= len; - } - return false; + return rc; } bool session_update(THD *thd, set_var *var) { diff --git a/sql/table.cc b/sql/table.cc index fc9c2b9db70..449b848f9bb 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -50,6 +50,7 @@ #include "wsrep_schema.h" #endif #include "log_event.h" // MAX_TABLE_MAP_ID +#include "sql_class.h" /* For MySQL 5.7 virtual fields */ #define MYSQL57_GENERATED_FIELD 128 @@ -5868,6 +5869,59 @@ void TABLE::reset_item_list(List *item_list, uint skip) const } } +TABLE_LIST::TABLE_LIST(THD *thd, + LEX_CSTRING db_str, + bool fqtn, + LEX_CSTRING alias_str, + bool has_alias_ptr, + Table_ident *table_ident, + thr_lock_type lock_t, + enum_mdl_type mdl_t, + ulong table_opts, + bool info_schema, + st_select_lex *sel, + List *index_hints_ptr, + LEX_STRING *option_ptr) +{ + db= db_str; + is_fqtn= fqtn; + alias= alias_str; + is_alias= has_alias_ptr; + if (lower_case_table_names) + { + if (table_ident->table.length) + table_ident->table.length= my_casedn_str(files_charset_info, + (char*) table_ident->table.str); + if (db.length && db.str != any_db.str) + db.length= my_casedn_str(files_charset_info, (char*) db.str); + } + + table_name= table_ident->table; + lock_type= lock_t; + mdl_type= mdl_t; + table_options= table_opts; + updating= table_options & TL_OPTION_UPDATING; + /* TODO: remove TL_OPTION_FORCE_INDEX as it looks like it's not used */ + force_index= table_options & TL_OPTION_FORCE_INDEX; + ignore_leaves= table_options & TL_OPTION_IGNORE_LEAVES; + sequence= table_options & TL_OPTION_SEQUENCE; + derived= table_ident->sel; + + if (!table_ident->sel && info_schema) + { + schema_table= find_schema_table(thd, &table_name); + schema_table_name= table_name; + } + select_lex= sel; + /* + We can't cache internal temporary tables between prepares as the + table may be deleted before next exection. + */ + cacheable_table= !table_ident->is_derived_table(); + index_hints= index_hints_ptr; + option= option_ptr ? option_ptr->str : 0; +} + /* calculate md5 of query diff --git a/sql/table.h b/sql/table.h index da90d56eeed..b0b0f0323cd 100644 --- a/sql/table.h +++ b/sql/table.h @@ -2220,8 +2220,23 @@ struct TABLE_CHAIN void set_end_pos(TABLE_LIST **pos) { end_pos= pos; } }; +class Table_ident; struct TABLE_LIST { + TABLE_LIST(THD *thd, + LEX_CSTRING db_str, + bool fqtn, + LEX_CSTRING alias_str, + bool has_alias_ptr, + Table_ident *table_ident, + thr_lock_type lock_t, + enum_mdl_type mdl_t, + ulong table_opts, + bool info_schema, + st_select_lex *sel, + List *index_hints_ptr, + LEX_STRING *option_ptr); + TABLE_LIST() = default; /* Remove gcc warning */ enum prelocking_types diff --git a/sql/tztime.cc b/sql/tztime.cc index 8ddb9f0e30e..e6cebbbd59f 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -2725,6 +2725,8 @@ static const char *lock_tables= " time_zone_transition WRITE,\n" " time_zone_transition_type WRITE"; static const char *trunc_tables_const= + "SET @old_alter_alg=@@SESSION.alter_algorithm;\n" + "SET session alter_algorithm='COPY';\n" "TRUNCATE TABLE time_zone;\n" "TRUNCATE TABLE time_zone_name;\n" "TRUNCATE TABLE time_zone_transition;\n" @@ -2873,6 +2875,9 @@ main(int argc, char **argv) "concat('ALTER TABLE time_zone_transition_type ENGINE=', " "@time_zone_transition_type_engine, ', ORDER BY Time_zone_id, Transition_type_id'), 'do 0');\n"); + if (argc == 1 && !opt_leap) + printf("SET session alter_algorithm=@old_alter_alg;\n"); + free_allocated_data(); my_end(0); return 0; diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index e9e49736c5a..fde5433296b 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1128,10 +1128,8 @@ void wsrep_recover() } } - -void wsrep_stop_replication(THD *thd) +static void wsrep_stop_replication_common(THD *thd) { - WSREP_INFO("Stop replication by %llu", (thd) ? thd->thread_id : 0); if (Wsrep_server_state::instance().state() != Wsrep_server_state::s_disconnected) { @@ -1144,10 +1142,10 @@ void wsrep_stop_replication(THD *thd) } } - /* my connection, should not terminate with wsrep_close_client_connection(), - make transaction to rollback - */ - if (thd && !thd->wsrep_applier) trans_rollback(thd); + /* my connection, should not terminate with + wsrep_close_client_connections(), make transaction to rollback */ + if (thd && !thd->wsrep_applier) + trans_rollback(thd); wsrep_close_client_connections(TRUE, thd); /* wait until appliers have stopped */ @@ -1156,26 +1154,16 @@ void wsrep_stop_replication(THD *thd) node_uuid= WSREP_UUID_UNDEFINED; } +void wsrep_stop_replication(THD *thd) +{ + WSREP_INFO("Stop replication by %llu", (thd) ? thd->thread_id : 0); + wsrep_stop_replication_common(thd); +} + void wsrep_shutdown_replication() { WSREP_INFO("Shutdown replication"); - if (Wsrep_server_state::instance().state() != wsrep::server_state::s_disconnected) - { - WSREP_DEBUG("Disconnect provider"); - Wsrep_server_state::instance().disconnect(); - if (Wsrep_server_state::instance().wait_until_state( - Wsrep_server_state::s_disconnected)) - { - WSREP_WARN("Wsrep interrupted while waiting for disconnected state"); - } - } - - wsrep_close_client_connections(TRUE); - - /* wait until appliers have stopped */ - wsrep_wait_appliers_close(NULL); - node_uuid= WSREP_UUID_UNDEFINED; - + wsrep_stop_replication_common(nullptr); /* Undocking the thread specific data. */ set_current_thd(nullptr); } @@ -3350,14 +3338,20 @@ static my_bool have_client_connections(THD *thd, void*) { DBUG_PRINT("quit",("Informing thread %lld that it's time to die", (longlong) thd->thread_id)); - if (is_client_connection(thd) && - (thd->killed == KILL_CONNECTION || - thd->killed == KILL_CONNECTION_HARD)) + if (is_client_connection(thd)) { - (void)abort_replicated(thd); - return 1; + if (thd->killed == KILL_CONNECTION || + thd->killed == KILL_CONNECTION_HARD) + { + (void)abort_replicated(thd); + return true; + } + if (thd->get_stmt_da()->is_eof()) + { + return true; + } } - return 0; + return false; } static void wsrep_close_thread(THD *thd) @@ -3395,14 +3389,24 @@ static my_bool kill_all_threads(THD *thd, THD *caller_thd) /* We skip slave threads & scheduler on this first loop through. */ if (is_client_connection(thd) && thd != caller_thd) { + if (thd->get_stmt_da()->is_eof()) + { + return 0; + } + if (is_replaying_connection(thd)) + { thd->set_killed(KILL_CONNECTION_HARD); - else if (!abort_replicated(thd)) + return 0; + } + + if (!abort_replicated(thd)) { /* replicated transactions must be skipped */ WSREP_DEBUG("closing connection %lld", (longlong) thd->thread_id); /* instead of wsrep_close_thread() we do now soft kill by THD::awake */ thd->awake(KILL_CONNECTION_HARD); + return 0; } } return 0; @@ -3414,6 +3418,7 @@ static my_bool kill_remaining_threads(THD *thd, THD *caller_thd) if (is_client_connection(thd) && !abort_replicated(thd) && !is_replaying_connection(thd) && + !thd->get_stmt_da()->is_eof() && thd_is_connection_alive(thd) && thd != caller_thd) { diff --git a/sql/wsrep_schema.cc b/sql/wsrep_schema.cc index c6e45340dd1..5d090670464 100644 --- a/sql/wsrep_schema.cc +++ b/sql/wsrep_schema.cc @@ -272,25 +272,17 @@ static void finish_stmt(THD* thd) { close_thread_tables(thd); } -static int open_table(THD* thd, - const LEX_CSTRING *schema_name, - const LEX_CSTRING *table_name, - enum thr_lock_type const lock_type, - TABLE** table) { - assert(table); - *table= NULL; - +static int open_table(THD *thd, const LEX_CSTRING *schema_name, + const LEX_CSTRING *table_name, + enum thr_lock_type const lock_type, + TABLE_LIST *table_list) +{ + assert(table_list); DBUG_ENTER("Wsrep_schema::open_table()"); - - TABLE_LIST tables; - uint flags= (MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK | - MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY | - MYSQL_OPEN_IGNORE_FLUSH | - MYSQL_LOCK_IGNORE_TIMEOUT); - - tables.init_one_table(schema_name, - table_name, - NULL, lock_type); + const uint flags= (MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK | + MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY | + MYSQL_OPEN_IGNORE_FLUSH | MYSQL_LOCK_IGNORE_TIMEOUT); + table_list->init_one_table(schema_name, table_name, NULL, lock_type); thd->lex->query_tables_own_last= 0; // No need to open table if the query was bf aborted, @@ -300,37 +292,39 @@ static int open_table(THD* thd, (thd->get_stmt_da()->sql_errno() == ER_QUERY_INTERRUPTED)); if (interrupted || - !open_n_lock_single_table(thd, &tables, tables.lock_type, flags)) { + !open_n_lock_single_table(thd, table_list, table_list->lock_type, flags)) + { close_thread_tables(thd); DBUG_RETURN(1); } - *table= tables.table; - (*table)->use_all_columns(); + table_list->table->use_all_columns(); DBUG_RETURN(0); } - -static int open_for_write(THD* thd, const char* table_name, TABLE** table) { +static int open_for_write(THD* thd, const char* table_name, TABLE_LIST* table_list) +{ LEX_CSTRING schema_str= { wsrep_schema_str.c_str(), wsrep_schema_str.length() }; LEX_CSTRING table_str= { table_name, strlen(table_name) }; if (Wsrep_schema_impl::open_table(thd, &schema_str, &table_str, TL_WRITE, - table)) { + table_list)) + { // No need to log an error if the query was bf aborted, // thd client will get ER_LOCK_DEADLOCK in the end. const bool interrupted= thd->killed || (thd->is_error() && (thd->get_stmt_da()->sql_errno() == ER_QUERY_INTERRUPTED)); - if (!interrupted) { + if (!interrupted) + { WSREP_ERROR("Failed to open table %s.%s for writing", schema_str.str, table_name); } return 1; } - empty_record(*table); - (*table)->use_all_columns(); - restore_record(*table, s->default_values); + empty_record(table_list->table); + table_list->table->use_all_columns(); + restore_record(table_list->table, s->default_values); return 0; } @@ -479,19 +473,21 @@ static int delete_row(TABLE* table) { return 0; } -static int open_for_read(THD* thd, const char* table_name, TABLE** table) { - +static int open_for_read(THD *thd, const char *table_name, + TABLE_LIST *table_list) +{ LEX_CSTRING schema_str= { wsrep_schema_str.c_str(), wsrep_schema_str.length() }; LEX_CSTRING table_str= { table_name, strlen(table_name) }; if (Wsrep_schema_impl::open_table(thd, &schema_str, &table_str, TL_READ, - table)) { + table_list)) + { WSREP_ERROR("Failed to open table %s.%s for reading", schema_str.str, table_name); return 1; } - empty_record(*table); - (*table)->use_all_columns(); - restore_record(*table, s->default_values); + empty_record(table_list->table); + table_list->table->use_all_columns(); + restore_record(table_list->table, s->default_values); return 0; } @@ -752,8 +748,10 @@ int Wsrep_schema::store_view(THD* thd, const Wsrep_view& view) assert(view.status() == Wsrep_view::primary); int ret= 1; int error; + TABLE_LIST cluster_table_l; TABLE* cluster_table= 0; - TABLE* members_table= 0; + TABLE_LIST members_table_l; + TABLE* members_table = 0; #ifdef WSREP_SCHEMA_MEMBERS_HISTORY TABLE* members_history_table= 0; #endif /* WSREP_SCHEMA_MEMBERS_HISTORY */ @@ -778,11 +776,13 @@ int Wsrep_schema::store_view(THD* thd, const Wsrep_view& view) Store cluster view info */ Wsrep_schema_impl::init_stmt(thd); - if (Wsrep_schema_impl::open_for_write(thd, cluster_table_str.c_str(), &cluster_table)) + if (Wsrep_schema_impl::open_for_write(thd, cluster_table_str.c_str(), &cluster_table_l)) { goto out; } + cluster_table= cluster_table_l.table; + Wsrep_schema_impl::store(cluster_table, 0, view.state_id().id()); Wsrep_schema_impl::store(cluster_table, 1, view.view_seqno().get()); Wsrep_schema_impl::store(cluster_table, 2, view.state_id().seqno().get()); @@ -802,12 +802,14 @@ int Wsrep_schema::store_view(THD* thd, const Wsrep_view& view) */ Wsrep_schema_impl::init_stmt(thd); if (Wsrep_schema_impl::open_for_write(thd, members_table_str.c_str(), - &members_table)) + &members_table_l)) { WSREP_ERROR("failed to open wsrep.members table"); goto out; } + members_table= members_table_l.table; + for (size_t i= 0; i < view.members().size(); ++i) { Wsrep_schema_impl::store(members_table, 0, view.members()[i].id()); @@ -861,8 +863,10 @@ Wsrep_view Wsrep_schema::restore_view(THD* thd, const Wsrep_id& own_id) const { int ret= 1; int error; + TABLE_LIST cluster_table_l; TABLE* cluster_table= 0; bool end_cluster_scan= false; + TABLE_LIST members_table_l; TABLE* members_table= 0; bool end_members_scan= false; @@ -888,8 +892,12 @@ Wsrep_view Wsrep_schema::restore_view(THD* thd, const Wsrep_id& own_id) const { Read cluster info from cluster table */ Wsrep_schema_impl::init_stmt(thd); - if (Wsrep_schema_impl::open_for_read(thd, cluster_table_str.c_str(), &cluster_table) || - Wsrep_schema_impl::init_for_scan(cluster_table)) { + if (Wsrep_schema_impl::open_for_read(thd, cluster_table_str.c_str(), &cluster_table_l)) { + goto out; + } + cluster_table = cluster_table_l.table; + + if (Wsrep_schema_impl::init_for_scan(cluster_table)) { goto out; } @@ -913,8 +921,14 @@ Wsrep_view Wsrep_schema::restore_view(THD* thd, const Wsrep_id& own_id) const { Read members from members table */ Wsrep_schema_impl::init_stmt(thd); - if (Wsrep_schema_impl::open_for_read(thd, members_table_str.c_str(), &members_table) || - Wsrep_schema_impl::init_for_scan(members_table)) { + if (Wsrep_schema_impl::open_for_read(thd, members_table_str.c_str(), + &members_table_l)) + { + goto out; + } + + members_table= members_table_l.table; + if (Wsrep_schema_impl::init_for_scan(members_table)) { goto out; } end_members_scan= true; @@ -1018,14 +1032,15 @@ int Wsrep_schema::append_fragment(THD* thd, Wsrep_schema_impl::sql_safe_updates sql_safe_updates(thd); Wsrep_schema_impl::init_stmt(thd); - TABLE* frag_table= 0; - if (Wsrep_schema_impl::open_for_write(thd, sr_table_str.c_str(), &frag_table)) + TABLE_LIST frag_table_l; + if (Wsrep_schema_impl::open_for_write(thd, sr_table_str.c_str(), &frag_table_l)) { trans_rollback_stmt(thd); thd->lex->restore_backup_query_tables_list(&query_tables_list_backup); DBUG_RETURN(1); } + TABLE* frag_table= frag_table_l.table; Wsrep_schema_impl::store(frag_table, 0, server_id); Wsrep_schema_impl::store(frag_table, 1, transaction_id.get()); Wsrep_schema_impl::store(frag_table, 2, seqno.get()); @@ -1069,13 +1084,15 @@ int Wsrep_schema::update_fragment_meta(THD* thd, uchar *key=NULL; key_part_map key_map= 0; TABLE* frag_table= 0; + TABLE_LIST frag_table_l; Wsrep_schema_impl::init_stmt(thd); - if (Wsrep_schema_impl::open_for_write(thd, sr_table_str.c_str(), &frag_table)) + if (Wsrep_schema_impl::open_for_write(thd, sr_table_str.c_str(), &frag_table_l)) { thd->lex->restore_backup_query_tables_list(&query_tables_list_backup); DBUG_RETURN(1); } + frag_table= frag_table_l.table; /* Find record with the given uuid, trx id, and seqno -1 */ Wsrep_schema_impl::store(frag_table, 0, ws_meta.server_id()); @@ -1163,7 +1180,10 @@ static int remove_fragment(THD* thd, seqno.get(), error); } - ret= error; + else + { + ret= error; + } } else if (Wsrep_schema_impl::delete_row(frag_table)) { @@ -1195,12 +1215,14 @@ int Wsrep_schema::remove_fragments(THD* thd, thd->reset_n_backup_open_tables_state(&open_tables_backup); TABLE* frag_table= 0; - if (Wsrep_schema_impl::open_for_write(thd, sr_table_str.c_str(), &frag_table)) + TABLE_LIST frag_table_l; + if (Wsrep_schema_impl::open_for_write(thd, sr_table_str.c_str(), &frag_table_l)) { ret= 1; } else { + frag_table= frag_table_l.table; for (std::vector::const_iterator i= fragments.begin(); i != fragments.end(); ++i) { @@ -1264,6 +1286,7 @@ int Wsrep_schema::replay_transaction(THD* orig_thd, int ret= 1; int error; TABLE* frag_table= 0; + TABLE_LIST frag_table_l; uchar *key=NULL; key_part_map key_map= 0; @@ -1271,12 +1294,13 @@ int Wsrep_schema::replay_transaction(THD* orig_thd, i != fragments.end(); ++i) { Wsrep_schema_impl::init_stmt(&thd); - if ((error= Wsrep_schema_impl::open_for_read(&thd, sr_table_str.c_str(), &frag_table))) + if ((error= Wsrep_schema_impl::open_for_read(&thd, sr_table_str.c_str(), &frag_table_l))) { WSREP_WARN("Could not open SR table for read: %d", error); Wsrep_schema_impl::finish_stmt(&thd); DBUG_RETURN(1); } + frag_table= frag_table_l.table; Wsrep_schema_impl::store(frag_table, 0, ws_meta.server_id()); Wsrep_schema_impl::store(frag_table, 1, ws_meta.transaction_id().get()); @@ -1322,12 +1346,13 @@ int Wsrep_schema::replay_transaction(THD* orig_thd, if ((error= Wsrep_schema_impl::open_for_write(&thd, sr_table_str.c_str(), - &frag_table))) + &frag_table_l))) { WSREP_WARN("Could not open SR table for write: %d", error); Wsrep_schema_impl::finish_stmt(&thd); DBUG_RETURN(1); } + frag_table= frag_table_l.table; error= Wsrep_schema_impl::init_for_index_scan(frag_table, key, @@ -1369,7 +1394,9 @@ int Wsrep_schema::recover_sr_transactions(THD *orig_thd) (char*) &storage_thd); wsrep_assign_from_threadvars(&storage_thd); TABLE* frag_table= 0; + TABLE_LIST frag_table_l; TABLE* cluster_table= 0; + TABLE_LIST cluster_table_l; Wsrep_storage_service storage_service(&storage_thd); Wsrep_schema_impl::binlog_off binlog_off(&storage_thd); Wsrep_schema_impl::wsrep_off wsrep_off(&storage_thd); @@ -1384,10 +1411,15 @@ int Wsrep_schema::recover_sr_transactions(THD *orig_thd) Wsrep_schema_impl::init_stmt(&storage_thd); storage_thd.wsrep_skip_locking= FALSE; - if (Wsrep_schema_impl::open_for_read(&storage_thd, - cluster_table_str.c_str(), - &cluster_table) || - Wsrep_schema_impl::init_for_scan(cluster_table)) + if (Wsrep_schema_impl::open_for_read(&storage_thd, cluster_table_str.c_str(), + &cluster_table_l)) + { + Wsrep_schema_impl::finish_stmt(&storage_thd); + DBUG_RETURN(1); + } + cluster_table= cluster_table_l.table; + + if (Wsrep_schema_impl::init_for_scan(cluster_table)) { Wsrep_schema_impl::finish_stmt(&storage_thd); DBUG_RETURN(1); @@ -1425,12 +1457,19 @@ int Wsrep_schema::recover_sr_transactions(THD *orig_thd) Open the table for reading and writing so that fragments without valid seqno can be deleted. */ - if (Wsrep_schema_impl::open_for_write(&storage_thd, sr_table_str.c_str(), &frag_table) || - Wsrep_schema_impl::init_for_scan(frag_table)) + if (Wsrep_schema_impl::open_for_write(&storage_thd, sr_table_str.c_str(), + &frag_table_l)) { WSREP_ERROR("Failed to open SR table for write"); goto out; } + frag_table= frag_table_l.table; + + if (Wsrep_schema_impl::init_for_scan(frag_table)) + { + WSREP_ERROR("Failed to init for index scan"); + goto out; + } while (0 == error) { @@ -1521,13 +1560,15 @@ void Wsrep_schema::clear_allowlist() thd->thread_stack= (char*)&thd; wsrep_init_thd_for_schema(thd); TABLE* allowlist_table= 0; + TABLE_LIST allowlist_table_l; int error= 0; Wsrep_schema_impl::init_stmt(thd); if (Wsrep_schema_impl::open_for_write(thd, allowlist_table_str.c_str(), - &allowlist_table) || - Wsrep_schema_impl::init_for_scan(allowlist_table)) + &allowlist_table_l) || + (allowlist_table= allowlist_table_l.table, + Wsrep_schema_impl::init_for_scan(allowlist_table))) { WSREP_ERROR("Failed to open mysql.wsrep_allowlist table"); goto out; @@ -1567,14 +1608,16 @@ void Wsrep_schema::store_allowlist(std::vector& ip_allowlist) thd->thread_stack= (char*)&thd; wsrep_init_thd_for_schema(thd); TABLE* allowlist_table= 0; + TABLE_LIST allowlist_table_l; int error; Wsrep_schema_impl::init_stmt(thd); if (Wsrep_schema_impl::open_for_write(thd, allowlist_table_str.c_str(), - &allowlist_table)) + &allowlist_table_l)) { WSREP_ERROR("Failed to open mysql.wsrep_allowlist table"); goto out; } + allowlist_table= allowlist_table_l.table; for (size_t i= 0; i < ip_allowlist.size(); ++i) { Wsrep_schema_impl::store(allowlist_table, 0, ip_allowlist[i]); @@ -1618,6 +1661,7 @@ static void *allowlist_check_thread(void *param) int error; TABLE *allowlist_table= 0; + TABLE_LIST allowlist_table_l; bool match_found_or_empty= false; bool table_have_rows= false; char row[64]= { @@ -1629,8 +1673,9 @@ static void *allowlist_check_thread(void *param) */ Wsrep_schema_impl::init_stmt(&thd); if (Wsrep_schema_impl::open_for_read(&thd, allowlist_table_str.c_str(), - &allowlist_table) || - Wsrep_schema_impl::init_for_scan(allowlist_table)) + &allowlist_table_l) || + (allowlist_table= allowlist_table_l.table, + Wsrep_schema_impl::init_for_scan(allowlist_table))) { goto out; } diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index 6f99680eadf..5f01f8c9704 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -140,7 +140,6 @@ SET(INNOBASE_SOURCES btr/btr0pcur.cc btr/btr0sea.cc btr/btr0defragment.cc - buf/buf0block_hint.cc buf/buf0buddy.cc buf/buf0buf.cc buf/buf0dblwr.cc diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 47d9e5fbe00..6b3a37335c4 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -264,6 +264,8 @@ btr_root_block_get( mtr_t* mtr, /*!< in: mtr */ dberr_t* err) /*!< out: error code */ { + ut_ad(mode != RW_NO_LATCH); + if (!index->table || !index->table->space) { *err= DB_TABLESPACE_NOT_FOUND; @@ -285,13 +287,12 @@ btr_root_block_get( if (UNIV_LIKELY(block != nullptr)) { - if (UNIV_UNLIKELY(mode == RW_NO_LATCH)); - else if (!!page_is_comp(block->page.frame) != - index->table->not_redundant() || - btr_page_get_index_id(block->page.frame) != index->id || - !fil_page_index_page_check(block->page.frame) || - index->is_spatial() != - (fil_page_get_type(block->page.frame) == FIL_PAGE_RTREE)) + if (!!page_is_comp(block->page.frame) != + index->table->not_redundant() || + btr_page_get_index_id(block->page.frame) != index->id || + !fil_page_index_page_check(block->page.frame) || + index->is_spatial() != + (fil_page_get_type(block->page.frame) == FIL_PAGE_RTREE)) { *err= DB_PAGE_CORRUPTED; block= nullptr; @@ -561,13 +562,39 @@ btr_page_alloc_for_ibuf( { buf_page_make_young_if_needed(&new_block->page); *err= flst_remove(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, new_block, - PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr); + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, + fil_system.sys_space->free_limit, mtr); } ut_d(if (*err == DB_SUCCESS) flst_validate(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr)); return new_block; } +static MY_ATTRIBUTE((nonnull, warn_unused_result)) +/** Acquire a latch on the index root page for allocating or freeing pages. +@param index index tree +@param mtr mini-transaction +@param err error code +@return root page +@retval nullptr if an error occurred */ +buf_block_t *btr_root_block_sx(dict_index_t *index, mtr_t *mtr, dberr_t *err) +{ + buf_block_t *root= + mtr->get_already_latched(page_id_t{index->table->space_id, index->page}, + MTR_MEMO_PAGE_SX_FIX); + if (!root) + { + root= btr_root_block_get(index, RW_SX_LATCH, mtr, err); + if (UNIV_UNLIKELY(!root)) + return root; + } +#ifdef BTR_CUR_HASH_ADAPT + else + ut_ad(!root->index || !root->index->freed()); +#endif + return root; +} + /**************************************************************//** Allocates a new file page to be used in an index tree. NOTE: we assume that the caller has made the reservation for free extents! @@ -589,21 +616,9 @@ btr_page_alloc_low( page should be initialized. */ dberr_t* err) /*!< out: error code */ { - const auto savepoint= mtr->get_savepoint(); - buf_block_t *root= btr_root_block_get(index, RW_NO_LATCH, mtr, err); + buf_block_t *root= btr_root_block_sx(index, mtr, err); if (UNIV_UNLIKELY(!root)) return root; - - const bool have_latch= mtr->have_u_or_x_latch(*root); -#ifdef BTR_CUR_HASH_ADAPT - ut_ad(!have_latch || !root->index || !root->index->freed()); -#endif - mtr->rollback_to_savepoint(savepoint); - - if (!have_latch && - UNIV_UNLIKELY(!(root= btr_root_block_get(index, RW_SX_LATCH, mtr, err)))) - return root; - fseg_header_t *seg_header= root->page.frame + (level ? PAGE_HEADER + PAGE_BTR_SEG_TOP : PAGE_HEADER + PAGE_BTR_SEG_LEAF); return fseg_alloc_free_page_general(seg_header, hint_page_no, file_direction, @@ -652,7 +667,8 @@ btr_page_free_for_ibuf( buf_block_t *root= btr_get_latched_root(*index, mtr); dberr_t err= flst_add_first(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, - block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr); + block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, + fil_system.sys_space->free_limit, mtr); ut_d(if (err == DB_SUCCESS) flst_validate(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr)); return err; @@ -696,24 +712,16 @@ dberr_t btr_page_free(dict_index_t* index, buf_block_t* block, mtr_t* mtr, fil_space_t *space= index->table->space; dberr_t err; - const auto savepoint= mtr->get_savepoint(); - if (buf_block_t *root= btr_root_block_get(index, RW_NO_LATCH, mtr, &err)) + if (buf_block_t *root= btr_root_block_sx(index, mtr, &err)) { - const bool have_latch= mtr->have_u_or_x_latch(*root); -#ifdef BTR_CUR_HASH_ADAPT - ut_ad(!have_latch || !root->index || !root->index->freed()); -#endif - mtr->rollback_to_savepoint(savepoint); - if (have_latch || - (root= btr_root_block_get(index, RW_SX_LATCH, mtr, &err))) - err= fseg_free_page(&root->page.frame[blob || - page_is_leaf(block->page.frame) - ? PAGE_HEADER + PAGE_BTR_SEG_LEAF - : PAGE_HEADER + PAGE_BTR_SEG_TOP], - space, page, mtr, space_latched); + err= fseg_free_page(&root->page.frame[blob || + page_is_leaf(block->page.frame) + ? PAGE_HEADER + PAGE_BTR_SEG_LEAF + : PAGE_HEADER + PAGE_BTR_SEG_TOP], + space, page, mtr, space_latched); + if (err == DB_SUCCESS) + buf_page_free(space, page, mtr); } - if (err == DB_SUCCESS) - buf_page_free(space, page, mtr); /* The page was marked free in the allocation bitmap, but it should remain exclusively latched until mtr_t::commit() or until it diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index 5bf68c5833f..e2513ad6c32 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.cc @@ -837,7 +837,7 @@ PageBulk::release() m_block->page.fix(); /* No other threads can modify this block. */ - m_modify_clock = buf_block_get_modify_clock(m_block); + m_modify_clock = m_block->modify_clock; m_mtr.commit(); } diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 46afb73b3ff..a395142af22 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -935,7 +935,7 @@ static inline page_cur_mode_t btr_cur_nonleaf_mode(page_cur_mode_t mode) return PAGE_CUR_LE; } -static MY_ATTRIBUTE((nonnull)) +MY_ATTRIBUTE((nonnull,warn_unused_result)) /** Acquire a latch on the previous page without violating the latching order. @param block index page @param page_id page identifier with valid space identifier @@ -946,8 +946,9 @@ static MY_ATTRIBUTE((nonnull)) @retval 0 if an error occurred @retval 1 if the page could be latched in the wrong order @retval -1 if the latch on block was temporarily released */ -int btr_latch_prev(buf_block_t *block, page_id_t page_id, ulint zip_size, - rw_lock_type_t rw_latch, mtr_t *mtr, dberr_t *err) +static int btr_latch_prev(buf_block_t *block, page_id_t page_id, + ulint zip_size, + rw_lock_type_t rw_latch, mtr_t *mtr, dberr_t *err) { ut_ad(rw_latch == RW_S_LATCH || rw_latch == RW_X_LATCH); ut_ad(page_id.space() == block->page.id().space()); @@ -955,47 +956,80 @@ int btr_latch_prev(buf_block_t *block, page_id_t page_id, ulint zip_size, const auto prev_savepoint= mtr->get_savepoint(); ut_ad(block == mtr->at_savepoint(prev_savepoint - 1)); - page_id.set_page_no(btr_page_get_prev(block->page.frame)); + const page_t *const page= block->page.frame; + page_id.set_page_no(btr_page_get_prev(page)); + /* We are holding a latch on the current page. + + We will start by buffer-fixing the left sibling. Waiting for a latch + on it while holding a latch on the current page could lead to a + deadlock, because another thread could hold that latch and wait for + a right sibling page latch (the current page). + + If there is a conflict, we will temporarily release our latch on the + current block while waiting for a latch on the left sibling. The + buffer-fixes on both blocks will prevent eviction. */ + + retry: buf_block_t *prev= buf_page_get_gen(page_id, zip_size, RW_NO_LATCH, nullptr, BUF_GET, mtr, err, false); if (UNIV_UNLIKELY(!prev)) return 0; int ret= 1; - if (UNIV_UNLIKELY(rw_latch == RW_S_LATCH)) + static_assert(MTR_MEMO_PAGE_S_FIX == mtr_memo_type_t(BTR_SEARCH_LEAF), ""); + static_assert(MTR_MEMO_PAGE_X_FIX == mtr_memo_type_t(BTR_MODIFY_LEAF), ""); + + if (rw_latch == RW_S_LATCH + ? prev->page.lock.s_lock_try() : prev->page.lock.x_lock_try()) { - if (UNIV_LIKELY(prev->page.lock.s_lock_try())) + mtr->lock_register(prev_savepoint, mtr_memo_type_t(rw_latch)); + if (UNIV_UNLIKELY(prev->page.id() != page_id)) { - mtr->lock_register(prev_savepoint, MTR_MEMO_PAGE_S_FIX); - goto prev_latched; + fail: + /* the page was just read and found to be corrupted */ + mtr->rollback_to_savepoint(prev_savepoint); + return 0; } - block->page.lock.s_unlock(); } else { - if (UNIV_LIKELY(prev->page.lock.x_lock_try())) + ut_ad(mtr->at_savepoint(mtr->get_savepoint() - 1)->page.id() == page_id); + mtr->release_last_page(); + if (rw_latch == RW_S_LATCH) + block->page.lock.s_unlock(); + else + block->page.lock.x_unlock(); + + prev= buf_page_get_gen(page_id, zip_size, rw_latch, prev, + BUF_GET, mtr, err); + if (rw_latch == RW_S_LATCH) + block->page.lock.s_lock(); + else + block->page.lock.x_lock(); + + const page_id_t prev_page_id= page_id; + page_id.set_page_no(btr_page_get_prev(page)); + + if (UNIV_UNLIKELY(page_id != prev_page_id)) { - mtr->lock_register(prev_savepoint, MTR_MEMO_PAGE_X_FIX); - goto prev_latched; + mtr->release_last_page(); + if (page_id.page_no() == FIL_NULL) + return -1; + goto retry; } - block->page.lock.x_unlock(); + + if (UNIV_UNLIKELY(!prev)) + goto fail; + + ret= -1; } - ret= -1; - mtr->lock_register(prev_savepoint - 1, MTR_MEMO_BUF_FIX); - mtr->rollback_to_savepoint(prev_savepoint); - prev= buf_page_get_gen(page_id, zip_size, rw_latch, prev, - BUF_GET, mtr, err, false); - if (UNIV_UNLIKELY(!prev)) - return 0; - mtr->upgrade_buffer_fix(prev_savepoint - 1, rw_latch); - - prev_latched: - if (memcmp_aligned<2>(FIL_PAGE_TYPE + prev->page.frame, - FIL_PAGE_TYPE + block->page.frame, 2) || - memcmp_aligned<2>(PAGE_HEADER + PAGE_INDEX_ID + prev->page.frame, - PAGE_HEADER + PAGE_INDEX_ID + block->page.frame, 8) || - page_is_comp(prev->page.frame) != page_is_comp(block->page.frame)) + const page_t *const p= prev->page.frame; + if (memcmp_aligned<4>(FIL_PAGE_NEXT + p, FIL_PAGE_OFFSET + page, 4) || + memcmp_aligned<2>(FIL_PAGE_TYPE + p, FIL_PAGE_TYPE + page, 2) || + memcmp_aligned<2>(PAGE_HEADER + PAGE_INDEX_ID + p, + PAGE_HEADER + PAGE_INDEX_ID + page, 8) || + page_is_comp(p) != page_is_comp(page)) { ut_ad("corrupted" == 0); // FIXME: remove this *err= DB_CORRUPTION; @@ -6092,7 +6126,6 @@ btr_store_big_rec_extern_fields( for (ulint blob_npages = 0;; ++blob_npages) { buf_block_t* block; const ulint commit_freq = 4; - uint32_t r_extents; ut_ad(page_align(field_ref) == page_align(rec)); @@ -6127,22 +6160,14 @@ btr_store_big_rec_extern_fields( hint_prev = rec_block->page.id().page_no(); } - error = fsp_reserve_free_extents( - &r_extents, index->table->space, 1, - FSP_BLOB, &mtr, 1); - if (UNIV_UNLIKELY(error != DB_SUCCESS)) { -alloc_fail: - mtr.commit(); - goto func_exit; - } - block = btr_page_alloc(index, hint_prev + 1, FSP_NO_DIR, 0, &mtr, &mtr, &error); - index->table->space->release_free_extents(r_extents); if (!block) { - goto alloc_fail; +alloc_fail: + mtr.commit(); + goto func_exit; } const uint32_t space_id = block->page.id().space(); diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc index 2131fb9474d..de0f9e93f4d 100644 --- a/storage/innobase/btr/btr0pcur.cc +++ b/storage/innobase/btr/btr0pcur.cc @@ -179,10 +179,8 @@ before_first: cursor->old_n_fields, &cursor->old_rec_buf, &cursor->buf_size); - cursor->block_when_stored.store(block); - - /* Function try to check if block is S/X latch. */ - cursor->modify_clock = buf_block_get_modify_clock(block); + cursor->old_page_id = block->page.id(); + cursor->modify_clock = block->modify_clock; } /**************************************************************//** @@ -214,101 +212,80 @@ btr_pcur_copy_stored_position( } /** Optimistically latches the leaf page or pages requested. -@param[in] block guessed buffer block -@param[in,out] pcur cursor -@param[in,out] latch_mode BTR_SEARCH_LEAF, ... -@param[in,out] mtr mini-transaction -@return true if success */ +@param pcur persistent cursor +@param latch_mode BTR_SEARCH_LEAF, ... +@param mtr mini-transaction +@return true on success */ TRANSACTIONAL_TARGET -static bool btr_pcur_optimistic_latch_leaves(buf_block_t *block, - btr_pcur_t *pcur, +static bool btr_pcur_optimistic_latch_leaves(btr_pcur_t *pcur, btr_latch_mode *latch_mode, mtr_t *mtr) { - ut_ad(block->page.buf_fix_count()); - ut_ad(block->page.in_file()); - ut_ad(block->page.frame); - static_assert(BTR_SEARCH_PREV & BTR_SEARCH_LEAF, ""); static_assert(BTR_MODIFY_PREV & BTR_MODIFY_LEAF, ""); static_assert((BTR_SEARCH_PREV ^ BTR_MODIFY_PREV) == (RW_S_LATCH ^ RW_X_LATCH), ""); + buf_block_t *const block= + buf_page_optimistic_fix(pcur->btr_cur.page_cur.block, pcur->old_page_id); + + if (!block) + return false; + + if (*latch_mode == BTR_SEARCH_LEAF || *latch_mode == BTR_MODIFY_LEAF) + return buf_page_optimistic_get(block, rw_lock_type_t(*latch_mode), + pcur->modify_clock, mtr); + + ut_ad(*latch_mode == BTR_SEARCH_PREV || *latch_mode == BTR_MODIFY_PREV); const rw_lock_type_t mode= rw_lock_type_t(*latch_mode & (RW_X_LATCH | RW_S_LATCH)); - switch (*latch_mode) { - default: - ut_ad(*latch_mode == BTR_SEARCH_LEAF || *latch_mode == BTR_MODIFY_LEAF); - return buf_page_optimistic_get(mode, block, pcur->modify_clock, mtr); - case BTR_SEARCH_PREV: - case BTR_MODIFY_PREV: - page_id_t id{0}; - uint32_t left_page_no; - ulint zip_size; - buf_block_t *left_block= nullptr; - { - transactional_shared_lock_guard g{block->page.lock}; - if (block->modify_clock != pcur->modify_clock) - return false; - id= block->page.id(); - zip_size= block->zip_size(); - left_page_no= btr_page_get_prev(block->page.frame); - } + uint64_t modify_clock; + uint32_t left_page_no; + const page_t *const page= block->page.frame; + { + transactional_shared_lock_guard g{block->page.lock}; + modify_clock= block->modify_clock; + left_page_no= btr_page_get_prev(page); + } - if (left_page_no != FIL_NULL) - { - left_block= - buf_page_get_gen(page_id_t(id.space(), left_page_no), zip_size, - mode, nullptr, BUF_GET_POSSIBLY_FREED, mtr); + const auto savepoint= mtr->get_savepoint(); + mtr->memo_push(block, MTR_MEMO_BUF_FIX); - if (!left_block); - else if (btr_page_get_next(left_block->page.frame) != id.page_no()) - { -release_left_block: - mtr->release_last_page(); - return false; - } - else - buf_page_make_young_if_needed(&left_block->page); - } - - if (buf_page_optimistic_get(mode, block, pcur->modify_clock, mtr)) - { - if (btr_page_get_prev(block->page.frame) == left_page_no) - { - /* block was already buffer-fixed while entering the function and - buf_page_optimistic_get() buffer-fixes it again. */ - ut_ad(2 <= block->page.buf_fix_count()); - *latch_mode= btr_latch_mode(mode); - return true; - } - - mtr->release_last_page(); - } - - ut_ad(block->page.buf_fix_count()); - if (left_block) - goto release_left_block; + if (UNIV_UNLIKELY(modify_clock != pcur->modify_clock)) + { + fail: + mtr->rollback_to_savepoint(savepoint); return false; } -} -/** Structure acts as functor to do the latching of leaf pages. -It returns true if latching of leaf pages succeeded and false -otherwise. */ -struct optimistic_latch_leaves -{ - btr_pcur_t *const cursor; - btr_latch_mode *const latch_mode; - mtr_t *const mtr; - - bool operator()(buf_block_t *hint) const + buf_block_t *prev; + if (left_page_no != FIL_NULL) { - return hint && - btr_pcur_optimistic_latch_leaves(hint, cursor, latch_mode, mtr); + prev= buf_page_get_gen(page_id_t(pcur->old_page_id.space(), + left_page_no), block->zip_size(), + mode, nullptr, BUF_GET_POSSIBLY_FREED, mtr); + if (!prev || + page_is_comp(prev->page.frame) != page_is_comp(block->page.frame) || + memcmp_aligned<2>(block->page.frame, prev->page.frame, 2) || + memcmp_aligned<2>(block->page.frame + PAGE_HEADER + PAGE_INDEX_ID, + prev->page.frame + PAGE_HEADER + PAGE_INDEX_ID, 8)) + goto fail; } -}; + else + prev= nullptr; + + mtr->upgrade_buffer_fix(savepoint, mode); + + if (UNIV_UNLIKELY(block->modify_clock != modify_clock) || + UNIV_UNLIKELY(block->page.is_freed()) || + (prev && + memcmp_aligned<4>(FIL_PAGE_NEXT + prev->page.frame, + FIL_PAGE_OFFSET + page, 4))) + goto fail; + + return true; +} /** Restores the stored position of a persistent cursor bufferfixing the page and obtaining the specified latches. If the cursor position @@ -331,6 +308,7 @@ btr_pcur_t::SAME_UNIQ cursor position is on user rec and points on the record with the same unique field values as in the stored record, btr_pcur_t::NOT_SAME cursor position is not on user rec or points on the record with not the samebuniq field values as in the stored */ +TRANSACTIONAL_TARGET btr_pcur_t::restore_status btr_pcur_t::restore_position(btr_latch_mode restore_latch_mode, mtr_t *mtr) { @@ -361,7 +339,6 @@ btr_pcur_t::restore_position(btr_latch_mode restore_latch_mode, mtr_t *mtr) latch_mode = BTR_LATCH_MODE_WITHOUT_INTENTION(restore_latch_mode); pos_state = BTR_PCUR_IS_POSITIONED; - block_when_stored.clear(); return restore_status::NOT_SAME; } @@ -378,9 +355,8 @@ btr_pcur_t::restore_position(btr_latch_mode restore_latch_mode, mtr_t *mtr) case BTR_SEARCH_PREV: case BTR_MODIFY_PREV: /* Try optimistic restoration. */ - if (block_when_stored.run_with_hint( - optimistic_latch_leaves{this, &restore_latch_mode, - mtr})) { + if (btr_pcur_optimistic_latch_leaves(this, &restore_latch_mode, + mtr)) { pos_state = BTR_PCUR_IS_POSITIONED; latch_mode = restore_latch_mode; @@ -485,16 +461,22 @@ btr_pcur_t::restore_position(btr_latch_mode restore_latch_mode, mtr_t *mtr) since the cursor can now be on a different page! But we can retain the value of old_rec */ - block_when_stored.store(btr_pcur_get_block(this)); - modify_clock= buf_block_get_modify_clock( - block_when_stored.block()); + old_page_id = btr_cur.page_cur.block->page.id(); + modify_clock = btr_cur.page_cur.block->modify_clock; mem_heap_free(heap); return restore_status::SAME_ALL; } - if (n_matched_fields >= index->n_uniq) - ret_val= restore_status::SAME_UNIQ; + if (n_matched_fields >= index->n_uniq + /* Unique indexes can contain "NULL" keys, and if all + unique fields are NULL and not all tuple + fields match to record fields, then treat it as if + restored cursor position points to the record with + not the same unique key. */ + && !(index->n_nullable + && dtuple_contains_null(tuple, index->n_uniq))) + ret_val= restore_status::SAME_UNIQ; } mem_heap_free(heap); @@ -612,40 +594,33 @@ btr_pcur_move_backward_from_page( return true; } - buf_block_t* block = btr_pcur_get_block(cursor); + buf_block_t* block = mtr->at_savepoint(0); + ut_ad(block == btr_pcur_get_block(cursor)); + const page_t* const page = block->page.frame; + /* btr_pcur_optimistic_latch_leaves() will acquire a latch on + the preceding page if one exists; + if that fails, btr_cur_t::search_leaf() invoked by + btr_pcur_open_with_no_init() will also acquire a latch on the + succeeding page. Our caller only needs one page latch. */ + ut_ad(mtr->get_savepoint() <= 3); - if (page_has_prev(block->page.frame)) { - buf_block_t* left_block - = mtr->at_savepoint(mtr->get_savepoint() - 1); - const page_t* const left = left_block->page.frame; - if (memcmp_aligned<4>(left + FIL_PAGE_NEXT, - block->page.frame - + FIL_PAGE_OFFSET, 4)) { - /* This should be the right sibling page, or - if there is none, the current block. */ - ut_ad(left_block == block - || !memcmp_aligned<4>(left + FIL_PAGE_PREV, - block->page.frame - + FIL_PAGE_OFFSET, 4)); - /* The previous one must be the left sibling. */ - left_block - = mtr->at_savepoint(mtr->get_savepoint() - 2); - ut_ad(!memcmp_aligned<4>(left_block->page.frame - + FIL_PAGE_NEXT, - block->page.frame - + FIL_PAGE_OFFSET, 4)); - } + if (page_has_prev(page)) { + buf_block_t* const left_block = mtr->at_savepoint(1); + ut_ad(!memcmp_aligned<4>(page + FIL_PAGE_OFFSET, + left_block->page.frame + + FIL_PAGE_NEXT, 4)); if (btr_pcur_is_before_first_on_page(cursor)) { + /* Reposition on the previous page. */ page_cur_set_after_last(left_block, &cursor->btr_cur.page_cur); /* Release the right sibling. */ - } else { - /* Release the left sibling. */ + mtr->rollback_to_savepoint(0, 1); block = left_block; } - mtr->release(*block); } + mtr->rollback_to_savepoint(1); + ut_ad(block == mtr->at_savepoint(0)); cursor->latch_mode = latch_mode; cursor->old_rec = nullptr; return false; diff --git a/storage/innobase/buf/buf0block_hint.cc b/storage/innobase/buf/buf0block_hint.cc deleted file mode 100644 index 6bd01faa279..00000000000 --- a/storage/innobase/buf/buf0block_hint.cc +++ /dev/null @@ -1,59 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2020, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2020, 2021, MariaDB Corporation. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License, version 2.0, as published by the -Free Software Foundation. - -This program is also distributed with certain software (including but not -limited to OpenSSL) that is licensed under separate terms, as designated in a -particular file or component or in included license documentation. The authors -of MySQL hereby grant you an additional permission to link the program and -your derivative works with the separately licensed software that they have -included with MySQL. - -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, version 2.0, -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 "buf0block_hint.h" -namespace buf { - -TRANSACTIONAL_TARGET -void Block_hint::buffer_fix_block_if_still_valid() -{ - /* To check if m_block belongs to the current buf_pool, we must - prevent freeing memory while we check, and until we buffer-fix the - block. For this purpose it is enough to latch any of the many - latches taken by buf_pool_t::resize(). - - Similar to buf_page_optimistic_get(), we must validate - m_block->page.id() after acquiring the hash_lock, because the object - may have been freed and not actually attached to buf_pool.page_hash - at the moment. (The block could have been reused to store a - different page, and that slice of buf_pool.page_hash could be protected - by another hash_lock that we are not holding.) - - Finally, we must ensure that the block is not being freed. */ - if (m_block) - { - auto &cell= buf_pool.page_hash.cell_get(m_page_id.fold()); - transactional_shared_lock_guard g - {buf_pool.page_hash.lock_get(cell)}; - if (buf_pool.is_uncompressed(m_block) && m_page_id == m_block->page.id() && - m_block->page.frame && m_block->page.in_file()) - m_block->page.fix(); - else - clear(); - } -} -} // namespace buf diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index c30c1bb8199..4dfa2ec6c99 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -2860,9 +2860,10 @@ got_block_fixed: if (state > buf_page_t::READ_FIX && state < buf_page_t::WRITE_FIX) { if (mode == BUF_PEEK_IF_IN_POOL) { ignore_block: + block->unfix(); +ignore_unfixed: ut_ad(mode == BUF_GET_POSSIBLY_FREED || mode == BUF_PEEK_IF_IN_POOL); - block->unfix(); if (err) { *err = DB_CORRUPTION; } @@ -2883,9 +2884,17 @@ ignore_block: const page_id_t id{block->page.id()}; block->page.lock.s_unlock(); - if (UNIV_UNLIKELY(id != page_id)) { - ut_ad(id == page_id_t{~0ULL}); + if (UNIV_UNLIKELY(state < buf_page_t::UNFIXED)) { block->page.unfix(); + if (UNIV_UNLIKELY(id == page_id)) { + /* The page read was completed, and + another thread marked the page as free + while we were waiting. */ + goto ignore_unfixed; + } + + ut_ad(id == page_id_t{~0ULL}); + if (++retries < BUF_PAGE_READ_MAX_RETRIES) { goto loop; } @@ -2896,6 +2905,7 @@ ignore_block: return nullptr; } + ut_ad(id == page_id); } else if (mode != BUF_PEEK_IF_IN_POOL) { } else if (!mtr) { ut_ad(!block->page.oldest_modification()); @@ -3102,83 +3112,72 @@ re_evict_fail: #endif /* UNIV_DEBUG */ ut_ad(block->page.frame); + /* The state = block->page.state() may be stale at this point, + and in fact, at any point of time if we consider its + buffer-fix component. If the block is being read into the + buffer pool, it is possible that buf_page_t::read_complete() + will invoke buf_pool_t::corrupted_evict() and therefore + invalidate it (invoke buf_page_t::set_corrupt_id() and set the + state to FREED). Therefore, after acquiring the page latch we + must recheck the state. */ + if (state >= buf_page_t::UNFIXED && allow_ibuf_merge && fil_page_get_type(block->page.frame) == FIL_PAGE_INDEX && page_is_leaf(block->page.frame)) { block->page.lock.x_lock(); - ut_ad(block->page.id() == page_id - || (state >= buf_page_t::READ_FIX - && state < buf_page_t::WRITE_FIX)); - -#ifdef BTR_CUR_HASH_ADAPT - btr_search_drop_page_hash_index(block, true); -#endif /* BTR_CUR_HASH_ADAPT */ - - dberr_t e; - - if (UNIV_UNLIKELY(block->page.id() != page_id)) { -page_id_mismatch: - state = block->page.state(); - e = DB_CORRUPTION; -ibuf_merge_corrupted: - if (err) { - *err = e; - } - - if (block->page.id().is_corrupted()) { - buf_pool.corrupted_evict(&block->page, state); - } - return nullptr; - } - state = block->page.state(); ut_ad(state < buf_page_t::READ_FIX); if (state >= buf_page_t::IBUF_EXIST && state < buf_page_t::REINIT) { block->page.clear_ibuf_exist(); - e = ibuf_merge_or_delete_for_page(block, page_id, - block->zip_size()); - if (UNIV_UNLIKELY(e != DB_SUCCESS)) { - goto ibuf_merge_corrupted; + if (dberr_t local_err = + ibuf_merge_or_delete_for_page(block, page_id, + block->zip_size())) { + if (err) { + *err = local_err; + } + goto release_and_ignore_block; } + } else if (state < buf_page_t::UNFIXED) { +release_and_ignore_block: + block->page.lock.x_unlock(); + goto ignore_block; } - if (rw_latch == RW_X_LATCH) { - goto get_latch_valid; - } else { +#ifdef BTR_CUR_HASH_ADAPT + btr_search_drop_page_hash_index(block, true); +#endif /* BTR_CUR_HASH_ADAPT */ + + switch (rw_latch) { + case RW_NO_LATCH: block->page.lock.x_unlock(); - goto get_latch; + break; + case RW_S_LATCH: + block->page.lock.x_unlock(); + block->page.lock.s_lock(); + break; + case RW_SX_LATCH: + block->page.lock.x_u_downgrade(); + break; + default: + ut_ad(rw_latch == RW_X_LATCH); } + + mtr->memo_push(block, mtr_memo_type_t(rw_latch)); } else { -get_latch: switch (rw_latch) { case RW_NO_LATCH: mtr->memo_push(block, MTR_MEMO_BUF_FIX); return block; case RW_S_LATCH: block->page.lock.s_lock(); - ut_ad(!block->page.is_read_fixed()); - if (UNIV_UNLIKELY(block->page.id() != page_id)) { - block->page.lock.s_unlock(); - block->page.lock.x_lock(); - goto page_id_mismatch; - } -get_latch_valid: - mtr->memo_push(block, mtr_memo_type_t(rw_latch)); -#ifdef BTR_CUR_HASH_ADAPT - btr_search_drop_page_hash_index(block, true); -#endif /* BTR_CUR_HASH_ADAPT */ break; case RW_SX_LATCH: block->page.lock.u_lock(); ut_ad(!block->page.is_io_fixed()); - if (UNIV_UNLIKELY(block->page.id() != page_id)) { - block->page.lock.u_x_upgrade(); - goto page_id_mismatch; - } - goto get_latch_valid; + break; default: ut_ad(rw_latch == RW_X_LATCH); if (block->page.lock.x_lock_upgraded()) { @@ -3187,17 +3186,26 @@ get_latch_valid: mtr->page_lock_upgrade(*block); return block; } - if (UNIV_UNLIKELY(block->page.id() != page_id)) { - goto page_id_mismatch; - } - goto get_latch_valid; } - ut_ad(page_id_t(page_get_space_id(block->page.frame), - page_get_page_no(block->page.frame)) - == page_id); + mtr->memo_push(block, mtr_memo_type_t(rw_latch)); + state = block->page.state(); + + if (UNIV_UNLIKELY(state < buf_page_t::UNFIXED)) { + mtr->release_last_page(); + goto ignore_unfixed; + } + + ut_ad(state < buf_page_t::READ_FIX + || state > buf_page_t::WRITE_FIX); + +#ifdef BTR_CUR_HASH_ADAPT + btr_search_drop_page_hash_index(block, true); +#endif /* BTR_CUR_HASH_ADAPT */ } + ut_ad(page_id_t(page_get_space_id(block->page.frame), + page_get_page_no(block->page.frame)) == page_id); return block; } @@ -3293,83 +3301,76 @@ buf_page_get_gen( return block; } -/********************************************************************//** -This is the general function used to get optimistic access to a database -page. -@return TRUE if success */ TRANSACTIONAL_TARGET -bool buf_page_optimistic_get(ulint rw_latch, buf_block_t *block, - uint64_t modify_clock, mtr_t *mtr) +buf_block_t *buf_page_optimistic_fix(buf_block_t *block, page_id_t id) +{ + buf_pool_t::hash_chain &chain= buf_pool.page_hash.cell_get(id.fold()); + transactional_shared_lock_guard g + {buf_pool.page_hash.lock_get(chain)}; + if (UNIV_UNLIKELY(!buf_pool.is_uncompressed(block) || + id != block->page.id() || !block->page.frame)) + return nullptr; + const auto state= block->page.state(); + if (UNIV_UNLIKELY(state < buf_page_t::UNFIXED || + state >= buf_page_t::READ_FIX)) + return nullptr; + block->page.fix(); + return block; +} + +buf_block_t *buf_page_optimistic_get(buf_block_t *block, + rw_lock_type_t rw_latch, + uint64_t modify_clock, mtr_t *mtr) { - ut_ad(block); - ut_ad(mtr); ut_ad(mtr->is_active()); ut_ad(rw_latch == RW_S_LATCH || rw_latch == RW_X_LATCH); + ut_ad(block->page.buf_fix_count()); - if (have_transactional_memory); - else if (UNIV_UNLIKELY(!block->page.frame)) - return false; - else + if (rw_latch == RW_S_LATCH) { - const auto state= block->page.state(); - if (UNIV_UNLIKELY(state < buf_page_t::UNFIXED || - state >= buf_page_t::READ_FIX)) - return false; - } - - bool success; - const page_id_t id{block->page.id()}; - buf_pool_t::hash_chain &chain= buf_pool.page_hash.cell_get(id.fold()); - bool have_u_not_x= false; - - { - transactional_shared_lock_guard g - {buf_pool.page_hash.lock_get(chain)}; - if (UNIV_UNLIKELY(id != block->page.id() || !block->page.frame)) - return false; - const auto state= block->page.state(); - if (UNIV_UNLIKELY(state < buf_page_t::UNFIXED || - state >= buf_page_t::READ_FIX)) - return false; - - if (rw_latch == RW_S_LATCH) - success= block->page.lock.s_lock_try(); - else + if (!block->page.lock.s_lock_try()) { - have_u_not_x= block->page.lock.have_u_not_x(); - success= have_u_not_x || block->page.lock.x_lock_try(); + fail: + block->page.unfix(); + return nullptr; } - } - if (!success) - return false; - - if (have_u_not_x) - { - block->page.lock.u_x_upgrade(); - mtr->page_lock_upgrade(*block); - ut_ad(id == block->page.id()); - ut_ad(modify_clock == block->modify_clock); - } - else - { - ut_ad(rw_latch == RW_S_LATCH || !block->page.is_io_fixed()); - ut_ad(id == block->page.id()); - ut_ad(!ibuf_inside(mtr) || ibuf_page(id, block->zip_size(), nullptr)); + ut_ad(!ibuf_inside(mtr) || + ibuf_page(block->page.id(), block->zip_size(), nullptr)); if (modify_clock != block->modify_clock || block->page.is_freed()) { - if (rw_latch == RW_S_LATCH) - block->page.lock.s_unlock(); - else - block->page.lock.x_unlock(); - return false; + block->page.lock.s_unlock(); + goto fail; } - block->page.fix(); ut_ad(!block->page.is_read_fixed()); buf_page_make_young_if_needed(&block->page); - mtr->memo_push(block, mtr_memo_type_t(rw_latch)); + mtr->memo_push(block, MTR_MEMO_PAGE_S_FIX); + } + else if (block->page.lock.have_u_not_x()) + { + block->page.lock.u_x_upgrade(); + block->page.unfix(); + mtr->page_lock_upgrade(*block); + ut_ad(modify_clock == block->modify_clock); + } + else if (!block->page.lock.x_lock_try()) + goto fail; + else + { + ut_ad(!block->page.is_io_fixed()); + ut_ad(!ibuf_inside(mtr) || + ibuf_page(block->page.id(), block->zip_size(), nullptr)); + + if (modify_clock != block->modify_clock || block->page.is_freed()) + { + block->page.lock.x_unlock(); + goto fail; + } + + buf_page_make_young_if_needed(&block->page); + mtr->memo_push(block, MTR_MEMO_PAGE_X_FIX); } ut_d(if (!(++buf_dbg_counter % 5771)) buf_pool.validate()); @@ -3379,7 +3380,7 @@ bool buf_page_optimistic_get(ulint rw_latch, buf_block_t *block, ut_ad(~buf_page_t::LRU_MASK & state); ut_ad(block->page.frame); - return true; + return block; } /** Try to S-latch a page. diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 9567be8371d..a1295c3328c 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -2009,7 +2009,6 @@ dict_index_add_to_cache( new_index->n_fields = new_index->n_def; new_index->trx_id = index->trx_id; new_index->set_committed(index->is_committed()); - new_index->nulls_equal = index->nulls_equal; n_ord = new_index->n_uniq; /* Flag the ordering columns and also set column max_prefix */ diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index 97cb39940c8..d4e6c6f3f78 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -2290,7 +2290,7 @@ void fil_space_crypt_close_tablespace(const fil_space_t *space) << space->chain.start->name << " (" << space->id << ") active threads " << crypt_data->rotate_state.active_threads - << "flushing=" + << " flushing=" << crypt_data->rotate_state.flushing << "."; last = now; } diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 5488b2d8c02..5f34fe93301 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -259,6 +259,7 @@ inline void xdes_init(const buf_block_t &block, xdes_t *descr, mtr_t *mtr) } /** Mark a page used in an extent descriptor. +@param[in] space tablespace @param[in,out] seg_inode segment inode @param[in,out] iblock segment inode page @param[in] page page number @@ -268,7 +269,8 @@ inline void xdes_init(const buf_block_t &block, xdes_t *descr, mtr_t *mtr) @return error code */ static MY_ATTRIBUTE((nonnull, warn_unused_result)) dberr_t -fseg_mark_page_used(fseg_inode_t *seg_inode, buf_block_t *iblock, +fseg_mark_page_used(const fil_space_t *space, + fseg_inode_t *seg_inode, buf_block_t *iblock, uint32_t page, xdes_t *descr, buf_block_t *xdes, mtr_t *mtr) { ut_ad(fil_page_get_type(iblock->page.frame) == FIL_PAGE_INODE); @@ -278,15 +280,16 @@ fseg_mark_page_used(fseg_inode_t *seg_inode, buf_block_t *iblock, const uint16_t xoffset= uint16_t(descr - xdes->page.frame + XDES_FLST_NODE); const uint16_t ioffset= uint16_t(seg_inode - iblock->page.frame); + const uint32_t limit= space->free_limit; if (!xdes_get_n_used(descr)) { /* We move the extent from the free list to the NOT_FULL list */ if (dberr_t err= flst_remove(iblock, uint16_t(FSEG_FREE + ioffset), - xdes, xoffset, mtr)) + xdes, xoffset, limit, mtr)) return err; if (dberr_t err= flst_add_last(iblock, uint16_t(FSEG_NOT_FULL + ioffset), - xdes, xoffset, mtr)) + xdes, xoffset, limit, mtr)) return err; } @@ -303,10 +306,10 @@ fseg_mark_page_used(fseg_inode_t *seg_inode, buf_block_t *iblock, { /* We move the extent from the NOT_FULL list to the FULL list */ if (dberr_t err= flst_remove(iblock, uint16_t(FSEG_NOT_FULL + ioffset), - xdes, xoffset, mtr)) + xdes, xoffset, limit, mtr)) return err; if (dberr_t err= flst_add_last(iblock, uint16_t(FSEG_FULL + ioffset), - xdes, xoffset, mtr)) + xdes, xoffset, limit, mtr)) return err; mtr->write<4>(*iblock, seg_inode + FSEG_NOT_FULL_N_USED, not_full_n_used - FSP_EXTENT_SIZE); @@ -884,7 +887,7 @@ fsp_fill_free_list( xdes_set_free(*xdes, descr, FSP_IBUF_BITMAP_OFFSET, mtr); xdes_set_state(*xdes, descr, XDES_FREE_FRAG, mtr); if (dberr_t err= flst_add_last(header, FSP_HEADER_OFFSET + FSP_FREE_FRAG, - xdes, xoffset, mtr)) + xdes, xoffset, space->free_limit, mtr)) return err; byte *n_used= FSP_HEADER_OFFSET + FSP_FRAG_N_USED + header->page.frame; mtr->write<4>(*header, n_used, 2U + mach_read_from_4(n_used)); @@ -893,7 +896,7 @@ fsp_fill_free_list( { if (dberr_t err= flst_add_last(header, FSP_HEADER_OFFSET + FSP_FREE, - xdes, xoffset, mtr)) + xdes, xoffset, space->free_limit, mtr)) return err; count++; } @@ -944,7 +947,11 @@ corrupted: first = flst_get_first(FSP_HEADER_OFFSET + FSP_FREE + header->page.frame); - if (first.page == FIL_NULL) { + if (first.page >= space->free_limit) { + if (first.page != FIL_NULL) { + goto flst_corrupted; + } + *err = fsp_fill_free_list(false, space, header, mtr); if (UNIV_UNLIKELY(*err != DB_SUCCESS)) { goto corrupted; @@ -955,6 +962,17 @@ corrupted: if (first.page == FIL_NULL) { return nullptr; /* No free extents left */ } + if (first.page >= space->free_limit) { + goto flst_corrupted; + } + } + + if (first.boffset < FSP_HEADER_OFFSET + FSP_HEADER_SIZE + || first.boffset >= space->physical_size() + - (XDES_SIZE + FIL_PAGE_DATA_END)) { + flst_corrupted: + *err = DB_CORRUPTION; + goto corrupted; } descr = xdes_lst_get_descriptor(*space, first, mtr, @@ -967,7 +985,7 @@ corrupted: *err = flst_remove(header, FSP_HEADER_OFFSET + FSP_FREE, desc_block, static_cast(descr - desc_block->page.frame + XDES_FLST_NODE), - mtr); + space->free_limit, mtr); if (UNIV_UNLIKELY(*err != DB_SUCCESS)) { return nullptr; } @@ -984,11 +1002,12 @@ MY_ATTRIBUTE((nonnull, warn_unused_result)) @param[in,out] xdes extent descriptor page @param[in,out] descr extent descriptor @param[in] bit slot to allocate in the extent +@param[in] space tablespace @param[in,out] mtr mini-transaction @return error code */ static dberr_t fsp_alloc_from_free_frag(buf_block_t *header, buf_block_t *xdes, xdes_t *descr, - uint32_t bit, mtr_t *mtr) + uint32_t bit, fil_space_t *space, mtr_t *mtr) { if (UNIV_UNLIKELY(xdes_get_state(descr) != XDES_FREE_FRAG || !xdes_is_free(descr, bit))) @@ -1001,14 +1020,15 @@ fsp_alloc_from_free_frag(buf_block_t *header, buf_block_t *xdes, xdes_t *descr, if (xdes_is_full(descr)) { + const uint32_t limit= space->free_limit; /* The fragment is full: move it to another list */ const uint16_t xoffset= static_cast(descr - xdes->page.frame + XDES_FLST_NODE); if (dberr_t err= flst_remove(header, FSP_HEADER_OFFSET + FSP_FREE_FRAG, - xdes, xoffset, mtr)) + xdes, xoffset, limit, mtr)) return err; if (dberr_t err= flst_add_last(header, FSP_HEADER_OFFSET + FSP_FULL_FRAG, - xdes, xoffset, mtr)) + xdes, xoffset, limit, mtr)) return err; xdes_set_state(*xdes, descr, XDES_FULL_FRAG, mtr); n_used-= FSP_EXTENT_SIZE; @@ -1070,8 +1090,11 @@ buf_block_t *fsp_alloc_free_page(fil_space_t *space, uint32_t hint, /* Else take the first extent in free_frag list */ fil_addr_t first = flst_get_first(FSP_HEADER_OFFSET + FSP_FREE_FRAG + block->page.frame); - if (first.page == FIL_NULL) + if (first.page >= space->free_limit) { + if (first.page != FIL_NULL) + goto flst_corrupted; + /* There are no partially full fragments: allocate a free extent and add it to the FREE_FRAG list. NOTE that the allocation may have as a side-effect that an extent containing a descriptor @@ -1082,13 +1105,23 @@ buf_block_t *fsp_alloc_free_page(fil_space_t *space, uint32_t hint, return nullptr; *err= flst_add_last(block, FSP_HEADER_OFFSET + FSP_FREE_FRAG, xdes, static_cast(descr - xdes->page.frame + - XDES_FLST_NODE), mtr); + XDES_FLST_NODE), + space->free_limit, mtr); if (UNIV_UNLIKELY(*err != DB_SUCCESS)) return nullptr; xdes_set_state(*xdes, descr, XDES_FREE_FRAG, mtr); } else { + if (first.boffset < FSP_HEADER_OFFSET + FSP_HEADER_SIZE || + first.boffset >= space->physical_size() - + (XDES_SIZE + FIL_PAGE_DATA_END)) + { + flst_corrupted: + *err= DB_CORRUPTION; + goto err_exit; + } + descr= xdes_lst_get_descriptor(*space, first, mtr, &xdes, err); if (!descr) return nullptr; @@ -1135,7 +1168,7 @@ buf_block_t *fsp_alloc_free_page(fil_space_t *space, uint32_t hint, } } - *err= fsp_alloc_from_free_frag(block, xdes, descr, free, mtr); + *err= fsp_alloc_from_free_frag(block, xdes, descr, free, space, mtr); if (UNIV_UNLIKELY(*err != DB_SUCCESS)) goto corrupted; return fsp_page_create(space, page_no, init_mtr); @@ -1174,7 +1207,8 @@ static dberr_t fsp_free_extent(fil_space_t* space, uint32_t offset, space->free_len++; return flst_add_last(block, FSP_HEADER_OFFSET + FSP_FREE, xdes, static_cast(descr - xdes->page.frame + - XDES_FLST_NODE), mtr); + XDES_FLST_NODE), + space->free_limit, mtr); } MY_ATTRIBUTE((nonnull)) @@ -1228,16 +1262,17 @@ static dberr_t fsp_free_page(fil_space_t *space, uint32_t offset, mtr_t *mtr) const uint16_t xoffset= static_cast(descr - xdes->page.frame + XDES_FLST_NODE); + const uint32_t limit = space->free_limit; if (state == XDES_FULL_FRAG) { /* The fragment was full: move it to another list */ err = flst_remove(header, FSP_HEADER_OFFSET + FSP_FULL_FRAG, - xdes, xoffset, mtr); + xdes, xoffset, limit, mtr); if (UNIV_UNLIKELY(err != DB_SUCCESS)) { return err; } err = flst_add_last(header, FSP_HEADER_OFFSET + FSP_FREE_FRAG, - xdes, xoffset, mtr); + xdes, xoffset, limit, mtr); if (UNIV_UNLIKELY(err != DB_SUCCESS)) { return err; } @@ -1259,7 +1294,7 @@ static dberr_t fsp_free_page(fil_space_t *space, uint32_t offset, mtr_t *mtr) if (!xdes_get_n_used(descr)) { /* The extent has become free: move it to another list */ err = flst_remove(header, FSP_HEADER_OFFSET + FSP_FREE_FRAG, - xdes, xoffset, mtr); + xdes, xoffset, limit, mtr); if (err == DB_SUCCESS) { err = fsp_free_extent(space, offset, mtr); } @@ -1353,7 +1388,7 @@ static dberr_t fsp_alloc_seg_inode_page(fil_space_t *space, #endif return flst_add_last(header, FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE, - block, FSEG_INODE_PAGE_NODE, mtr); + block, FSEG_INODE_PAGE_NODE, space->free_limit, mtr); } MY_ATTRIBUTE((nonnull, warn_unused_result)) @@ -1409,12 +1444,13 @@ fsp_alloc_seg_inode(fil_space_t *space, buf_block_t *header, { /* There are no other unused headers left on the page: move it to another list */ + const uint32_t limit= space->free_limit; *err= flst_remove(header, FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE, - block, FSEG_INODE_PAGE_NODE, mtr); + block, FSEG_INODE_PAGE_NODE, limit, mtr); if (UNIV_UNLIKELY(*err != DB_SUCCESS)) return nullptr; *err= flst_add_last(header, FSP_HEADER_OFFSET + FSP_SEG_INODES_FULL, - block, FSEG_INODE_PAGE_NODE, mtr); + block, FSEG_INODE_PAGE_NODE, limit, mtr); if (UNIV_UNLIKELY(*err != DB_SUCCESS)) return nullptr; } @@ -1447,16 +1483,17 @@ static void fsp_free_seg_inode(fil_space_t *space, fseg_inode_t *inode, } const ulint physical_size= space->physical_size(); + const uint32_t limit= space->free_limit; if (ULINT_UNDEFINED == fsp_seg_inode_page_find_free(iblock->page.frame, 0, physical_size)) { /* Move the page to another list */ if (flst_remove(header, FSP_HEADER_OFFSET + FSP_SEG_INODES_FULL, - iblock, FSEG_INODE_PAGE_NODE, mtr) != DB_SUCCESS) + iblock, FSEG_INODE_PAGE_NODE, limit, mtr) != DB_SUCCESS) return; if (flst_add_last(header, FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE, - iblock, FSEG_INODE_PAGE_NODE, mtr) != DB_SUCCESS) + iblock, FSEG_INODE_PAGE_NODE, limit, mtr) != DB_SUCCESS) return; } @@ -1468,7 +1505,7 @@ static void fsp_free_seg_inode(fil_space_t *space, fseg_inode_t *inode, /* There are no other used headers left on the page: free it */ if (flst_remove(header, FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE, - iblock, FSEG_INODE_PAGE_NODE, mtr) == DB_SUCCESS) + iblock, FSEG_INODE_PAGE_NODE, limit, mtr) == DB_SUCCESS) fsp_free_page(space, iblock->page.id().page_no(), mtr); } @@ -1841,7 +1878,8 @@ static dberr_t fseg_fill_free_list(const fseg_inode_t *inode, static_cast(inode - iblock->page.frame + FSEG_FREE), xdes, static_cast(descr - xdes->page.frame + - XDES_FLST_NODE), mtr)) + XDES_FLST_NODE), + space->free_limit, mtr)) return err; xdes_set_state(*xdes, descr, XDES_FSEG, mtr); mtr->memcpy(*xdes, descr + XDES_ID, inode + FSEG_ID, 8); @@ -1876,11 +1914,25 @@ fseg_alloc_free_extent( ut_ad(!memcmp(FSEG_MAGIC_N_BYTES, FSEG_MAGIC_N + inode, 4)); ut_d(space->modify_check(*mtr)); + if (UNIV_UNLIKELY(page_offset(inode) < FSEG_ARR_OFFSET)) + { + corrupted: + *err= DB_CORRUPTION; + space->set_corrupted(); + return nullptr; + } + if (flst_get_len(inode + FSEG_FREE)) { + const fil_addr_t first= flst_get_first(inode + FSEG_FREE); + if (first.page >= space->free_limit || + first.boffset < FSP_HEADER_OFFSET + FSP_HEADER_SIZE || + first.boffset >= space->physical_size() - + (XDES_SIZE + FIL_PAGE_DATA_END)) + goto corrupted; + /* Segment free list is not empty, allocate from it */ - return xdes_lst_get_descriptor(*space, flst_get_first(inode + FSEG_FREE), - mtr, xdes, err); + return xdes_lst_get_descriptor(*space, first, mtr, xdes, err); } xdes_t* descr= fsp_alloc_free_extent(space, 0, xdes, mtr, err); @@ -1892,7 +1944,8 @@ fseg_alloc_free_extent( static_cast(inode - iblock->page.frame + FSEG_FREE), *xdes, static_cast(descr - (*xdes)->page.frame + - XDES_FLST_NODE), mtr); + XDES_FLST_NODE), + space->free_limit, mtr); if (UNIV_LIKELY(*err != DB_SUCCESS)) return nullptr; /* Try to fill the segment free list */ @@ -2033,7 +2086,8 @@ take_hinted_page: + FSEG_FREE), xdes, static_cast(ret_descr - xdes->page.frame - + XDES_FLST_NODE), mtr); + + XDES_FLST_NODE), + space->free_limit, mtr); if (UNIV_UNLIKELY(*err != DB_SUCCESS)) { return nullptr; } @@ -2079,6 +2133,14 @@ take_hinted_page: return nullptr; } + if (first.page >= space->free_limit + || first.boffset < FSP_HEADER_OFFSET + FSP_HEADER_SIZE + || first.boffset >= space->physical_size() + - (XDES_SIZE + FIL_PAGE_DATA_END)) { + *err= DB_CORRUPTION; + return nullptr; + } + ret_descr = xdes_lst_get_descriptor(*space, first, mtr, &xdes); if (!ret_descr) { return nullptr; @@ -2172,8 +2234,8 @@ got_hinted_page: ut_ad(xdes == xxdes); ut_ad(xdes_is_free(ret_descr, ret_page % extent_size)); - *err = fseg_mark_page_used(seg_inode, iblock, ret_page, - ret_descr, xdes, mtr); + *err = fseg_mark_page_used(space, seg_inode, iblock, ret_page, + ret_descr, xdes, mtr); if (UNIV_UNLIKELY(*err != DB_SUCCESS)) { return nullptr; } @@ -2514,18 +2576,19 @@ corrupted: const uint16_t xoffset= uint16_t(descr - xdes->page.frame + XDES_FLST_NODE); const uint16_t ioffset= uint16_t(seg_inode - iblock->page.frame); + const uint32_t limit = space->free_limit; if (xdes_is_full(descr)) { /* The fragment is full: move it to another list */ err = flst_remove(iblock, static_cast(FSEG_FULL + ioffset), - xdes, xoffset, mtr); + xdes, xoffset, limit, mtr); if (UNIV_UNLIKELY(err != DB_SUCCESS)) { return err; } err = flst_add_last(iblock, static_cast(FSEG_NOT_FULL + ioffset), - xdes, xoffset, mtr); + xdes, xoffset, limit, mtr); if (UNIV_UNLIKELY(err != DB_SUCCESS)) { return err; } @@ -2543,7 +2606,7 @@ corrupted: if (!xdes_get_n_used(descr)) { err = flst_remove(iblock, static_cast(FSEG_NOT_FULL + ioffset), - xdes, xoffset, mtr); + xdes, xoffset, limit, mtr); if (UNIV_UNLIKELY(err != DB_SUCCESS)) { return err; } @@ -2688,11 +2751,12 @@ fseg_free_extent( #endif /* BTR_CUR_HASH_ADAPT */ uint16_t lst; + uint32_t limit = space->free_limit; if (xdes_is_full(descr)) { lst = static_cast(FSEG_FULL + ioffset); remove: - err = flst_remove(iblock, lst, xdes, xoffset, mtr); + err = flst_remove(iblock, lst, xdes, xoffset, limit, mtr); if (UNIV_UNLIKELY(err != DB_SUCCESS)) { return err; } @@ -2702,7 +2766,7 @@ remove: } else { err = flst_remove( iblock, static_cast(FSEG_NOT_FULL + ioffset), - xdes, xoffset, mtr); + xdes, xoffset, limit, mtr); if (UNIV_UNLIKELY(err != DB_SUCCESS)) { return err; } @@ -2952,7 +3016,10 @@ fseg_get_first_extent( return nullptr; } - if (first.page == FIL_NULL) + if (first.page >= space->free_limit || + first.boffset < FSP_HEADER_OFFSET + FSP_HEADER_SIZE || + first.boffset >= space->physical_size() - + (XDES_SIZE + FIL_PAGE_DATA_END)) goto corrupted; return xdes_lst_get_descriptor(*space, first, mtr, nullptr, err); diff --git a/storage/innobase/fut/fut0lst.cc b/storage/innobase/fut/fut0lst.cc index a52027f28bc..48e2fbe38aa 100644 --- a/storage/innobase/fut/fut0lst.cc +++ b/storage/innobase/fut/fut0lst.cc @@ -113,17 +113,18 @@ static void flst_add_to_empty(buf_block_t *base, uint16_t boffset, } /** Insert a node after another one. -@param[in,out] base base node block -@param[in] boffset byte offset of the base node -@param[in,out] cur insert position block -@param[in] coffset byte offset of the insert position -@param[in,out] add block to be added -@param[in] aoffset byte offset of the block to be added -@param[in,out] mtr mini-transaction */ +@param base base node block +@param boffset byte offset of the base node +@param cur insert position block +@param coffset byte offset of the insert position +@param add block to be added +@param aoffset byte offset of the block to be added +@param limit fil_space_t::free_limit +@param mtr mini-transaction */ static dberr_t flst_insert_after(buf_block_t *base, uint16_t boffset, buf_block_t *cur, uint16_t coffset, buf_block_t *add, uint16_t aoffset, - mtr_t *mtr) + uint32_t limit, mtr_t *mtr) { ut_ad(base != cur || boffset != coffset); ut_ad(base != add || boffset != aoffset); @@ -139,6 +140,15 @@ static dberr_t flst_insert_after(buf_block_t *base, uint16_t boffset, MTR_MEMO_PAGE_SX_FIX)); fil_addr_t next_addr= flst_get_next_addr(cur->page.frame + coffset); + if (next_addr.page >= limit) + { + if (UNIV_UNLIKELY(next_addr.page != FIL_NULL)) + return DB_CORRUPTION; + } + else if (UNIV_UNLIKELY(next_addr.boffset < FIL_PAGE_DATA || + next_addr.boffset >= base->physical_size() - + FIL_PAGE_DATA_END)) + return DB_CORRUPTION; flst_write_addr(*add, add->page.frame + aoffset + FLST_PREV, cur->page.id().page_no(), coffset, mtr); @@ -167,18 +177,19 @@ static dberr_t flst_insert_after(buf_block_t *base, uint16_t boffset, } /** Insert a node before another one. -@param[in,out] base base node block -@param[in] boffset byte offset of the base node -@param[in,out] cur insert position block -@param[in] coffset byte offset of the insert position -@param[in,out] add block to be added -@param[in] aoffset byte offset of the block to be added -@param[in,out] mtr mini-transaction +@param base base node block +@param boffset byte offset of the base node +@param cur insert position block +@param coffset byte offset of the insert position +@param add block to be added +@param aoffset byte offset of the block to be added +@param limit fil_space_t::free_limit +@param mtr mini-transaction @return error code */ static dberr_t flst_insert_before(buf_block_t *base, uint16_t boffset, buf_block_t *cur, uint16_t coffset, buf_block_t *add, uint16_t aoffset, - mtr_t *mtr) + uint32_t limit, mtr_t *mtr) { ut_ad(base != cur || boffset != coffset); ut_ad(base != add || boffset != aoffset); @@ -194,6 +205,15 @@ static dberr_t flst_insert_before(buf_block_t *base, uint16_t boffset, MTR_MEMO_PAGE_SX_FIX)); fil_addr_t prev_addr= flst_get_prev_addr(cur->page.frame + coffset); + if (prev_addr.page >= limit) + { + if (UNIV_UNLIKELY(prev_addr.page != FIL_NULL)) + return DB_CORRUPTION; + } + else if (UNIV_UNLIKELY(prev_addr.boffset < FIL_PAGE_DATA || + prev_addr.boffset >= base->physical_size() - + FIL_PAGE_DATA_END)) + return DB_CORRUPTION; flst_write_addr(*add, add->page.frame + aoffset + FLST_PREV, prev_addr.page, prev_addr.boffset, mtr); @@ -234,14 +254,9 @@ void flst_init(const buf_block_t& block, byte *base, mtr_t *mtr) flst_zero_both(block, base + FLST_FIRST, mtr); } -/** Append a file list node to a list. -@param[in,out] base base node block -@param[in] boffset byte offset of the base node -@param[in,out] add block to be added -@param[in] aoffset byte offset of the node to be added -@param[in,outr] mtr mini-transaction */ dberr_t flst_add_last(buf_block_t *base, uint16_t boffset, - buf_block_t *add, uint16_t aoffset, mtr_t *mtr) + buf_block_t *add, uint16_t aoffset, + uint32_t limit, mtr_t *mtr) { ut_ad(base != add || boffset != aoffset); ut_ad(boffset < base->physical_size()); @@ -258,6 +273,13 @@ dberr_t flst_add_last(buf_block_t *base, uint16_t boffset, else { fil_addr_t addr= flst_get_last(base->page.frame + boffset); + if (UNIV_UNLIKELY(addr.page >= limit)) + return DB_CORRUPTION; + else if (UNIV_UNLIKELY(addr.boffset < FIL_PAGE_DATA || + addr.boffset >= base->physical_size() - + FIL_PAGE_DATA_END)) + return DB_CORRUPTION; + buf_block_t *cur= add; dberr_t err; if (addr.page != add->page.id().page_no() && @@ -266,19 +288,13 @@ dberr_t flst_add_last(buf_block_t *base, uint16_t boffset, BUF_GET_POSSIBLY_FREED, mtr, &err))) return err; return flst_insert_after(base, boffset, cur, addr.boffset, - add, aoffset, mtr); + add, aoffset, limit, mtr); } } -/** Prepend a file list node to a list. -@param[in,out] base base node block -@param[in] boffset byte offset of the base node -@param[in,out] add block to be added -@param[in] aoffset byte offset of the node to be added -@param[in,out] mtr mini-transaction -@return error code */ dberr_t flst_add_first(buf_block_t *base, uint16_t boffset, - buf_block_t *add, uint16_t aoffset, mtr_t *mtr) + buf_block_t *add, uint16_t aoffset, + uint32_t limit, mtr_t *mtr) { ut_ad(base != add || boffset != aoffset); ut_ad(boffset < base->physical_size()); @@ -296,6 +312,12 @@ dberr_t flst_add_first(buf_block_t *base, uint16_t boffset, else { fil_addr_t addr= flst_get_first(base->page.frame + boffset); + if (UNIV_UNLIKELY(addr.page >= limit)) + return DB_CORRUPTION; + else if (UNIV_UNLIKELY(addr.boffset < FIL_PAGE_DATA || + addr.boffset >= base->physical_size() - + FIL_PAGE_DATA_END)) + return DB_CORRUPTION; buf_block_t *cur= add; dberr_t err; if (addr.page != add->page.id().page_no() && @@ -304,19 +326,13 @@ dberr_t flst_add_first(buf_block_t *base, uint16_t boffset, BUF_GET_POSSIBLY_FREED, mtr, &err))) return err; return flst_insert_before(base, boffset, cur, addr.boffset, - add, aoffset, mtr); + add, aoffset, limit, mtr); } } -/** Remove a file list node. -@param[in,out] base base node block -@param[in] boffset byte offset of the base node -@param[in,out] cur block to be removed -@param[in] coffset byte offset of the current record to be removed -@param[in,out] mtr mini-transaction -@return error code */ dberr_t flst_remove(buf_block_t *base, uint16_t boffset, - buf_block_t *cur, uint16_t coffset, mtr_t *mtr) + buf_block_t *cur, uint16_t coffset, + uint32_t limit, mtr_t *mtr) { ut_ad(boffset < base->physical_size()); ut_ad(coffset < cur->physical_size()); @@ -329,9 +345,27 @@ dberr_t flst_remove(buf_block_t *base, uint16_t boffset, const fil_addr_t next_addr= flst_get_next_addr(cur->page.frame + coffset); dberr_t err= DB_SUCCESS; - if (prev_addr.page == FIL_NULL) + if (next_addr.page >= limit) + { + if (next_addr.page != FIL_NULL) + return DB_CORRUPTION; + } + else if (UNIV_UNLIKELY(next_addr.boffset < FIL_PAGE_DATA || + next_addr.boffset >= base->physical_size() - + FIL_PAGE_DATA_END)) + return DB_CORRUPTION; + + if (prev_addr.page >= limit) + { + if (prev_addr.page != FIL_NULL) + return DB_CORRUPTION; flst_write_addr(*base, base->page.frame + boffset + FLST_FIRST, next_addr.page, next_addr.boffset, mtr); + } + else if (UNIV_UNLIKELY(prev_addr.boffset < FIL_PAGE_DATA || + prev_addr.boffset >= base->physical_size() - + FIL_PAGE_DATA_END)) + return DB_CORRUPTION; else { buf_block_t *b= cur; @@ -375,25 +409,19 @@ void flst_validate(const buf_block_t *base, uint16_t boffset, mtr_t *mtr) ut_ad(mtr->memo_contains_flagged(base, MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX)); - /* We use two mini-transaction handles: the first is used to lock - the base node, and prevent other threads from modifying the list. - The second is used to traverse the list. We cannot run the second - mtr without committing it at times, because if the list is long, - the x-locked pages could fill the buffer, resulting in a deadlock. */ - mtr_t mtr2; - const uint32_t len= flst_get_len(base->page.frame + boffset); fil_addr_t addr= flst_get_first(base->page.frame + boffset); for (uint32_t i= len; i--; ) { - mtr2.start(); + ut_ad(addr.boffset >= FIL_PAGE_DATA); + ut_ad(addr.boffset < base->physical_size() - FIL_PAGE_DATA_END); const buf_block_t *b= buf_page_get_gen(page_id_t(base->page.id().space(), addr.page), base->zip_size(), RW_SX_LATCH, nullptr, BUF_GET, mtr); ut_ad(b); addr= flst_get_next_addr(b->page.frame + addr.boffset); - mtr2.commit(); + mtr->release_last_page(); } ut_ad(addr.page == FIL_NULL); @@ -402,13 +430,14 @@ void flst_validate(const buf_block_t *base, uint16_t boffset, mtr_t *mtr) for (uint32_t i= len; i--; ) { - mtr2.start(); + ut_ad(addr.boffset >= FIL_PAGE_DATA); + ut_ad(addr.boffset < base->physical_size() - FIL_PAGE_DATA_END); const buf_block_t *b= buf_page_get_gen(page_id_t(base->page.id().space(), addr.page), base->zip_size(), RW_SX_LATCH, nullptr, BUF_GET, mtr); ut_ad(b); addr= flst_get_prev_addr(b->page.frame + addr.boffset); - mtr2.commit(); + mtr->release_last_page(); } ut_ad(addr.page == FIL_NULL); diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc index 0df9a7ded9a..4aab68e9ca2 100644 --- a/storage/innobase/gis/gis0sea.cc +++ b/storage/innobase/gis/gis0sea.cc @@ -289,10 +289,6 @@ rtr_pcur_getnext_from_path( mtr->rollback_to_savepoint(1); } - ut_ad((my_latch_mode | 4) == BTR_CONT_MODIFY_TREE - || !page_is_leaf(btr_cur_get_page(btr_cur)) - || !btr_cur->page_cur.block->page.lock.have_any()); - const auto block_savepoint = mtr->get_savepoint(); block = buf_page_get_gen( page_id_t(index->table->space_id, @@ -511,7 +507,7 @@ rtr_pcur_move_to_next( mysql_mutex_unlock(&rtr_info->matches->rtr_match_mutex); cursor->btr_cur.page_cur.rec = rec.r_rec; - cursor->btr_cur.page_cur.block = &rtr_info->matches->block; + cursor->btr_cur.page_cur.block = rtr_info->matches->block; DEBUG_SYNC_C("rtr_pcur_move_to_next_return"); return(true); @@ -672,8 +668,13 @@ dberr_t rtr_search_to_nth_level(ulint level, const dtuple_t *tuple, buf_mode, mtr, &err, false); if (!block) { - if (err == DB_DECRYPTION_FAILED) - btr_decryption_failed(*index); + if (err) + { + err_exit: + if (err == DB_DECRYPTION_FAILED) + btr_decryption_failed(*index); + mtr->rollback_to_savepoint(savepoint); + } func_exit: if (UNIV_LIKELY_NULL(heap)) mem_heap_free(heap); @@ -737,7 +738,8 @@ dberr_t rtr_search_to_nth_level(ulint level, const dtuple_t *tuple, #endif } - if (height == 0) { + if (height == 0) + { if (rw_latch == RW_NO_LATCH) { ut_ad(block == mtr->at_savepoint(block_savepoint)); @@ -821,7 +823,7 @@ dberr_t rtr_search_to_nth_level(ulint level, const dtuple_t *tuple, if (page_cur_search_with_match(tuple, page_mode, &up_match, &low_match, &cur->page_cur, nullptr)) { err= DB_CORRUPTION; - goto func_exit; + goto err_exit; } } @@ -1316,21 +1318,15 @@ rtr_create_rtr_info( rtr_info->index = index; if (init_matches) { - rtr_info->heap = mem_heap_create(sizeof(*(rtr_info->matches))); rtr_info->matches = static_cast( - mem_heap_zalloc( - rtr_info->heap, - sizeof(*rtr_info->matches))); + ut_zalloc_nokey(sizeof *rtr_info->matches)); rtr_info->matches->matched_recs = UT_NEW_NOKEY(rtr_rec_vector()); - rtr_info->matches->bufp = page_align(rtr_info->matches->rec_buf - + UNIV_PAGE_SIZE_MAX + 1); mysql_mutex_init(rtr_match_mutex_key, &rtr_info->matches->rtr_match_mutex, nullptr); - rtr_info->matches->block.page.lock.init(); } rtr_info->path = UT_NEW_NOKEY(rtr_node_path_t()); @@ -1449,18 +1445,16 @@ rtr_clean_rtr_info( if (free_all) { if (rtr_info->matches) { - if (rtr_info->matches->matched_recs != NULL) { - UT_DELETE(rtr_info->matches->matched_recs); + if (rtr_info->matches->block) { + buf_block_free(rtr_info->matches->block); + rtr_info->matches->block = nullptr; } - rtr_info->matches->block.page.lock.free(); + UT_DELETE(rtr_info->matches->matched_recs); mysql_mutex_destroy( &rtr_info->matches->rtr_match_mutex); - } - - if (rtr_info->heap) { - mem_heap_free(rtr_info->heap); + ut_free(rtr_info->matches); } if (initialized) { @@ -1570,7 +1564,7 @@ rtr_check_discard_page( if (auto matches = rtr_info->matches) { mysql_mutex_lock(&matches->rtr_match_mutex); - if (matches->block.page.id() == id) { + if (matches->block->page.id() == id) { matches->matched_recs->clear(); matches->valid = false; } @@ -1584,23 +1578,6 @@ rtr_check_discard_page( lock_sys.prdt_page_free_from_discard(id, true); } -/** Structure acts as functor to get the optimistic access of the page. -It returns true if it successfully gets the page. */ -struct optimistic_get -{ - btr_pcur_t *const r_cursor; - mtr_t *const mtr; - - optimistic_get(btr_pcur_t *r_cursor,mtr_t *mtr) - :r_cursor(r_cursor), mtr(mtr) {} - - bool operator()(buf_block_t *hint) const - { - return hint && buf_page_optimistic_get( - RW_X_LATCH, hint, r_cursor->modify_clock, mtr); - } -}; - /** Restore the stored position of a persistent cursor bufferfixing the page */ static bool @@ -1632,8 +1609,11 @@ rtr_cur_restore_position( r_cursor->modify_clock = 100; ); - if (r_cursor->block_when_stored.run_with_hint( - optimistic_get(r_cursor, mtr))) { + if (buf_page_optimistic_fix(r_cursor->btr_cur.page_cur.block, + r_cursor->old_page_id) + && buf_page_optimistic_get(r_cursor->btr_cur.page_cur.block, + RW_X_LATCH, r_cursor->modify_clock, + mtr)) { ut_ad(r_cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_ad(r_cursor->rel_pos == BTR_PCUR_ON); @@ -1778,7 +1758,7 @@ rtr_leaf_push_match_rec( ulint data_len; rtr_rec_t rtr_rec; - buf = match_rec->block.page.frame + match_rec->used; + buf = match_rec->block->page.frame + match_rec->used; ut_ad(page_rec_is_leaf(rec)); copy = rec_copy(buf, rec, offsets); @@ -1875,43 +1855,6 @@ rtr_non_leaf_insert_stack_push( new_seq, level, child_no, my_cursor, mbr_inc); } -/** Copy a buf_block_t, except "block->page.lock". -@param[in,out] matches copy to match->block -@param[in] block block to copy */ -static -void -rtr_copy_buf( - matched_rec_t* matches, - const buf_block_t* block) -{ - /* Copy all members of "block" to "matches->block" except "lock". - We skip "lock" because it is not used - from the dummy buf_block_t we create here and because memcpy()ing - it generates (valid) compiler warnings that the vtable pointer - will be copied. */ - matches->block.page.lock.free(); - new (&matches->block.page) buf_page_t(block->page); - matches->block.page.frame = block->page.frame; - matches->block.unzip_LRU = block->unzip_LRU; - - ut_d(matches->block.in_unzip_LRU_list = block->in_unzip_LRU_list); - ut_d(matches->block.in_withdraw_list = block->in_withdraw_list); - - /* Skip buf_block_t::lock */ - matches->block.modify_clock = block->modify_clock; -#ifdef BTR_CUR_HASH_ADAPT - matches->block.n_hash_helps = block->n_hash_helps; - matches->block.n_fields = block->n_fields; - matches->block.left_side = block->left_side; -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - matches->block.n_pointers = 0; -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - matches->block.curr_n_fields = block->curr_n_fields; - matches->block.curr_left_side = block->curr_left_side; - matches->block.index = block->index; -#endif /* BTR_CUR_HASH_ADAPT */ -} - /****************************************************************//** Generate a shadow copy of the page block header to save the matched records */ @@ -1925,16 +1868,18 @@ rtr_init_match( { ut_ad(matches->matched_recs->empty()); matches->locked = false; - rtr_copy_buf(matches, block); - matches->block.page.frame = matches->bufp; matches->valid = false; + if (!matches->block) { + matches->block = buf_block_alloc(); + } + + matches->block->page.init(buf_page_t::MEMORY, block->page.id()); /* We have to copy PAGE_*_SUPREMUM_END bytes so that we can use infimum/supremum of this page as normal btr page for search. */ - memcpy(matches->block.page.frame, page, page_is_comp(page) - ? PAGE_NEW_SUPREMUM_END : PAGE_OLD_SUPREMUM_END); matches->used = page_is_comp(page) ? PAGE_NEW_SUPREMUM_END : PAGE_OLD_SUPREMUM_END; + memcpy(matches->block->page.frame, page, matches->used); #ifdef RTR_SEARCH_DIAGNOSTIC ulint pageno = page_get_page_no(page); fprintf(stderr, "INNODB_RTR: Searching leaf page %d\n", @@ -2361,7 +2306,7 @@ rtr_cur_search_with_match( #endif /* UNIV_DEBUG */ /* Pop the last match record and position on it */ match_rec->matched_recs->pop_back(); - page_cur_position(test_rec.r_rec, &match_rec->block, + page_cur_position(test_rec.r_rec, match_rec->block, cursor); } } else { diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 9dbee523536..fc8106b5cfc 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -7345,26 +7345,55 @@ ha_innobase::build_template( ulint num_v = 0; - if (active_index != MAX_KEY - && active_index == pushed_idx_cond_keyno) { - m_prebuilt->idx_cond = this; - goto icp; - } else if (pushed_rowid_filter && rowid_filter_is_active) { -icp: - /* Push down an index condition or an end_range check. */ + /* MDEV-31154: For pushed down index condition we don't support virtual + column and idx_cond_push() does check for it. For row ID filtering we + don't need such restrictions but we get into trouble trying to use the + ICP path. + + 1. It should be fine to follow no_icp path if primary key is generated. + However, with user specified primary key(PK), the row is identified by + the PK and those columns need to be converted to mysql format in + row_search_idx_cond_check before doing the comparison. Since secondary + indexes always have PK appended in innodb, it works with current ICP + handling code when fetch_primary_key_cols is set to TRUE. + + 2. Although ICP comparison and Row ID comparison works on different + columns the current ICP code can be shared by both. + + 3. In most cases, it works today by jumping to goto no_icp when we + encounter a virtual column. This is hackish and already have some + issues as it cannot handle PK and all states are not reset properly, + for example, idx_cond_n_cols is not reset. + + 4. We already encountered MDEV-28747 m_prebuilt->idx_cond was being set. + + Neither ICP nor row ID comparison needs virtual columns and the code is + simplified to handle both. It should handle the issues. */ + + const bool pushed_down = active_index != MAX_KEY + && active_index == pushed_idx_cond_keyno; + + m_prebuilt->idx_cond = pushed_down ? this : nullptr; + + if (m_prebuilt->idx_cond || m_prebuilt->pk_filter) { + /* Push down an index condition, end_range check or row ID + filter */ for (ulint i = 0; i < n_fields; i++) { const Field* field = table->field[i]; const bool is_v = !field->stored_in_db(); - if (is_v && skip_virtual) { - num_v++; - continue; - } + bool index_contains = index->contains_col_or_prefix( is_v ? num_v : i - num_v, is_v); - if (is_v && index_contains) { - m_prebuilt->n_template = 0; - num_v = 0; - goto no_icp; + + if (is_v) { + if (index_contains) { + /* We want to ensure that ICP is not + used with virtual columns. */ + ut_ad(!pushed_down); + m_prebuilt->idx_cond = nullptr; + } + num_v++; + continue; } /* Test if an end_range or an index condition @@ -7384,7 +7413,7 @@ icp: which would be acceptable if end_range==NULL. */ if (build_template_needs_field_in_icp( index, m_prebuilt, index_contains, - is_v ? num_v : i - num_v, is_v)) { + i - num_v, false)) { if (!whole_row) { field = build_template_needs_field( index_contains, @@ -7393,15 +7422,10 @@ icp: fetch_primary_key_cols, index, table, i, num_v); if (!field) { - if (is_v) { - num_v++; - } continue; } } - ut_ad(!is_v); - mysql_row_templ_t* templ= build_template_field( m_prebuilt, clust_index, index, table, field, i - num_v, 0); @@ -7478,15 +7502,16 @@ icp: */ } - if (is_v) { - num_v++; - } } - ut_ad(m_prebuilt->idx_cond_n_cols > 0); - ut_ad(m_prebuilt->idx_cond_n_cols == m_prebuilt->n_template); - num_v = 0; + ut_ad(m_prebuilt->idx_cond_n_cols == m_prebuilt->n_template); + if (m_prebuilt->idx_cond_n_cols == 0) { + /* No columns to push down. It is safe to jump to np ICP + path. */ + m_prebuilt->idx_cond = nullptr; + goto no_icp; + } /* Include the fields that are not needed in index condition pushdown. */ @@ -7501,7 +7526,7 @@ icp: bool index_contains = index->contains_col_or_prefix( is_v ? num_v : i - num_v, is_v); - if (!build_template_needs_field_in_icp( + if (is_v || !build_template_needs_field_in_icp( index, m_prebuilt, index_contains, is_v ? num_v : i - num_v, is_v)) { /* Not needed in ICP */ @@ -7534,7 +7559,7 @@ icp: } else { no_icp: /* No index condition pushdown */ - m_prebuilt->idx_cond = NULL; + ut_ad(!m_prebuilt->idx_cond); ut_ad(num_v == 0); for (ulint i = 0; i < n_fields; i++) { @@ -8795,47 +8820,63 @@ ha_innobase::index_end(void) DBUG_RETURN(0); } -/*********************************************************************//** -Converts a search mode flag understood by MySQL to a flag understood -by InnoDB. */ -page_cur_mode_t -convert_search_mode_to_innobase( -/*============================*/ - ha_rkey_function find_flag) +/** Convert a MariaDB search mode to an InnoDB search mode. +@tparam last_match whether last_match_mode is to be set +@param find_flag MariaDB search mode +@param mode InnoDB search mode +@param last_match_mode pointer to ha_innobase::m_last_match_mode +@return whether the search mode is unsupported */ +template +static bool convert_search_mode_to_innobase(ha_rkey_function find_flag, + page_cur_mode_t &mode, + uint *last_match_mode= nullptr) { - switch (find_flag) { - case HA_READ_KEY_EXACT: - /* this does not require the index to be UNIQUE */ - case HA_READ_KEY_OR_NEXT: - return(PAGE_CUR_GE); - case HA_READ_AFTER_KEY: - return(PAGE_CUR_G); - case HA_READ_BEFORE_KEY: - return(PAGE_CUR_L); - case HA_READ_KEY_OR_PREV: - case HA_READ_PREFIX_LAST: - case HA_READ_PREFIX_LAST_OR_PREV: - return(PAGE_CUR_LE); - case HA_READ_MBR_CONTAIN: - return(PAGE_CUR_CONTAIN); - case HA_READ_MBR_INTERSECT: - return(PAGE_CUR_INTERSECT); - case HA_READ_MBR_WITHIN: - return(PAGE_CUR_WITHIN); - case HA_READ_MBR_DISJOINT: - return(PAGE_CUR_DISJOINT); - case HA_READ_MBR_EQUAL: - return(PAGE_CUR_MBR_EQUAL); - case HA_READ_PREFIX: - return(PAGE_CUR_UNSUPP); - /* do not use "default:" in order to produce a gcc warning: - enumeration value '...' not handled in switch - (if -Wswitch or -Wall is used) */ - } + mode= PAGE_CUR_LE; + if (last_match) + *last_match_mode= 0; - my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "this functionality"); + switch (find_flag) { + case HA_READ_KEY_EXACT: + /* this does not require the index to be UNIQUE */ + if (last_match) + *last_match_mode= ROW_SEL_EXACT; + /* fall through */ + case HA_READ_KEY_OR_NEXT: + mode= PAGE_CUR_GE; + return false; + case HA_READ_AFTER_KEY: + mode= PAGE_CUR_G; + return false; + case HA_READ_BEFORE_KEY: + mode= PAGE_CUR_L; + return false; + case HA_READ_PREFIX_LAST: + if (last_match) + *last_match_mode= ROW_SEL_EXACT_PREFIX; + /* fall through */ + case HA_READ_KEY_OR_PREV: + case HA_READ_PREFIX_LAST_OR_PREV: + return false; + case HA_READ_MBR_CONTAIN: + mode= PAGE_CUR_CONTAIN; + return false; + case HA_READ_MBR_INTERSECT: + mode= PAGE_CUR_INTERSECT; + return false; + case HA_READ_MBR_WITHIN: + mode= PAGE_CUR_WITHIN; + return false; + case HA_READ_MBR_DISJOINT: + mode= PAGE_CUR_DISJOINT; + return false; + case HA_READ_MBR_EQUAL: + mode= PAGE_CUR_MBR_EQUAL; + return false; + case HA_READ_PREFIX: + break; + } - return(PAGE_CUR_UNSUPP); + return true; } /* @@ -8913,8 +8954,7 @@ ha_innobase::index_read( mariadb_set_stats set_stats_temporary(handler_stats); DEBUG_SYNC_C("ha_innobase_index_read_begin"); - ut_a(m_prebuilt->trx == thd_to_trx(m_user_thd)); - ut_ad(key_len != 0 || find_flag != HA_READ_KEY_EXACT); + ut_ad(m_prebuilt->trx == thd_to_trx(m_user_thd)); dict_index_t* index = m_prebuilt->index; @@ -8950,7 +8990,8 @@ ha_innobase::index_read( build_template(false); } - if (key_ptr != NULL) { + if (key_len) { + ut_ad(key_ptr); /* Convert the search key value to InnoDB format into m_prebuilt->search_tuple */ @@ -8960,84 +9001,58 @@ ha_innobase::index_read( m_prebuilt->srch_key_val_len, index, (byte*) key_ptr, - (ulint) key_len); + key_len); DBUG_ASSERT(m_prebuilt->search_tuple->n_fields > 0); } else { + ut_ad(find_flag != HA_READ_KEY_EXACT); /* We position the cursor to the last or the first entry in the index */ dtuple_set_n_fields(m_prebuilt->search_tuple, 0); } - page_cur_mode_t mode = convert_search_mode_to_innobase(find_flag); + page_cur_mode_t mode; - ulint match_mode = 0; - - if (find_flag == HA_READ_KEY_EXACT) { - - match_mode = ROW_SEL_EXACT; - - } else if (find_flag == HA_READ_PREFIX_LAST) { - - match_mode = ROW_SEL_EXACT_PREFIX; + if (convert_search_mode_to_innobase(find_flag, mode, + &m_last_match_mode)) { + table->status = STATUS_NOT_FOUND; + DBUG_RETURN(HA_ERR_UNSUPPORTED); } - m_last_match_mode = (uint) match_mode; - - dberr_t ret = mode == PAGE_CUR_UNSUPP ? DB_UNSUPPORTED - : row_search_mvcc(buf, mode, m_prebuilt, match_mode, 0); + dberr_t ret = + row_search_mvcc(buf, mode, m_prebuilt, m_last_match_mode, 0); DBUG_EXECUTE_IF("ib_select_query_failure", ret = DB_ERROR;); - int error; + if (UNIV_LIKELY(ret == DB_SUCCESS)) { + table->status = 0; + DBUG_RETURN(0); + } + + table->status = STATUS_NOT_FOUND; switch (ret) { - case DB_SUCCESS: - error = 0; - table->status = 0; - break; - - case DB_RECORD_NOT_FOUND: - error = HA_ERR_KEY_NOT_FOUND; - table->status = STATUS_NOT_FOUND; - break; - - case DB_END_OF_INDEX: - error = HA_ERR_KEY_NOT_FOUND; - table->status = STATUS_NOT_FOUND; - break; - case DB_TABLESPACE_DELETED: ib_senderrf( m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED, table->s->table_name.str); - - table->status = STATUS_NOT_FOUND; - error = HA_ERR_TABLESPACE_MISSING; - break; - + DBUG_RETURN(HA_ERR_TABLESPACE_MISSING); + case DB_RECORD_NOT_FOUND: + case DB_END_OF_INDEX: + DBUG_RETURN(HA_ERR_KEY_NOT_FOUND); case DB_TABLESPACE_NOT_FOUND: - ib_senderrf( m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_MISSING, table->s->table_name.str); - - table->status = STATUS_NOT_FOUND; - error = HA_ERR_TABLESPACE_MISSING; - break; - + DBUG_RETURN(HA_ERR_TABLESPACE_MISSING); default: - error = convert_error_code_to_mysql( - ret, m_prebuilt->table->flags, m_user_thd); - - table->status = STATUS_NOT_FOUND; - break; + DBUG_RETURN(convert_error_code_to_mysql( + ret, m_prebuilt->table->flags, + m_user_thd)); } - - DBUG_RETURN(error); } /*******************************************************************//** @@ -9464,8 +9479,6 @@ ha_innobase::rnd_pos( DBUG_ENTER("rnd_pos"); DBUG_DUMP("key", pos, ref_length); - ut_a(m_prebuilt->trx == thd_to_trx(ha_thd())); - /* Note that we assume the length of the row reference is fixed for the table, and it is == ref_length */ @@ -9889,7 +9902,8 @@ wsrep_append_foreign_key( } ulint rcode = DB_SUCCESS; - char cache_key[513] = {'\0'}; + char cache_key[MAX_FULL_NAME_LEN] = {'\0'}; + char db_name[MAX_DATABASE_NAME_LEN+1] = {'\0'}; size_t cache_key_len = 0; if ( !((referenced) ? @@ -9979,14 +9993,38 @@ wsrep_append_foreign_key( return DB_ERROR; } - strncpy(cache_key, + char * fk_table = (wsrep_protocol_version > 1) ? ((referenced) ? foreign->referenced_table->name.m_name : foreign->foreign_table->name.m_name) : - foreign->foreign_table->name.m_name, sizeof(cache_key) - 1); - cache_key_len = strlen(cache_key); + foreign->foreign_table->name.m_name; + /* convert db and table name parts separately to system charset */ + ulint db_name_len = dict_get_db_name_len(fk_table); + strmake(db_name, fk_table, db_name_len); + uint errors; + cache_key_len= innobase_convert_to_system_charset(cache_key, + db_name, sizeof(cache_key), &errors); + if (errors) { + WSREP_WARN("unexpected foreign key table %s %s", + foreign->referenced_table->name.m_name, + foreign->foreign_table->name.m_name); + return DB_ERROR; + } + + /* after db name adding 0 and then converted table name */ + cache_key[db_name_len]= '\0'; + cache_key_len++; + + cache_key_len+= innobase_convert_to_system_charset(cache_key+cache_key_len, + fk_table+db_name_len+1, sizeof(cache_key), &errors); + if (errors) { + WSREP_WARN("unexpected foreign key table %s %s", + foreign->referenced_table->name.m_name, + foreign->foreign_table->name.m_name); + return DB_ERROR; + } #ifdef WSREP_DEBUG_PRINT ulint j; fprintf(stderr, "FK parent key, table: %s %s len: %lu ", @@ -9996,16 +10034,6 @@ wsrep_append_foreign_key( } fprintf(stderr, "\n"); #endif - char *p = strchr(cache_key, '/'); - - if (p) { - *p = '\0'; - } else { - WSREP_WARN("unexpected foreign key table %s %s", - foreign->referenced_table->name.m_name, - foreign->foreign_table->name.m_name); - } - wsrep_buf_t wkey_part[3]; wsrep_key_t wkey = {wkey_part, 3}; @@ -14188,14 +14216,14 @@ ha_innobase::records_in_range( dict_index_t* index; dtuple_t* range_start; dtuple_t* range_end; - ha_rows n_rows; + ha_rows n_rows = HA_POS_ERROR; page_cur_mode_t mode1; page_cur_mode_t mode2; mem_heap_t* heap; DBUG_ENTER("records_in_range"); - ut_a(m_prebuilt->trx == thd_to_trx(ha_thd())); + ut_ad(m_prebuilt->trx == thd_to_trx(ha_thd())); m_prebuilt->trx->op_info = "estimating records in index range"; @@ -14208,12 +14236,7 @@ ha_innobase::records_in_range( /* There exists possibility of not being able to find requested index due to inconsistency between MySQL and InoDB dictionary info. Necessary message should have been printed in innobase_get_index() */ - if (!m_prebuilt->table->space) { - n_rows = HA_POS_ERROR; - goto func_exit; - } - if (!index) { - n_rows = HA_POS_ERROR; + if (!index || !m_prebuilt->table->space) { goto func_exit; } if (index->is_corrupted()) { @@ -14229,61 +14252,50 @@ ha_innobase::records_in_range( + sizeof(dtuple_t))); range_start = dtuple_create(heap, key->ext_key_parts); - dict_index_copy_types(range_start, index, key->ext_key_parts); range_end = dtuple_create(heap, key->ext_key_parts); - dict_index_copy_types(range_end, index, key->ext_key_parts); - row_sel_convert_mysql_key_to_innobase( - range_start, - m_prebuilt->srch_key_val1, - m_prebuilt->srch_key_val_len, - index, - (byte*) (min_key ? min_key->key : (const uchar*) 0), - (ulint) (min_key ? min_key->length : 0)); - - DBUG_ASSERT(min_key - ? range_start->n_fields > 0 - : range_start->n_fields == 0); - - row_sel_convert_mysql_key_to_innobase( - range_end, - m_prebuilt->srch_key_val2, - m_prebuilt->srch_key_val_len, - index, - (byte*) (max_key ? max_key->key : (const uchar*) 0), - (ulint) (max_key ? max_key->length : 0)); - - DBUG_ASSERT(max_key - ? range_end->n_fields > 0 - : range_end->n_fields == 0); - - mode1 = convert_search_mode_to_innobase( - min_key ? min_key->flag : HA_READ_KEY_EXACT); - - mode2 = convert_search_mode_to_innobase( - max_key ? max_key->flag : HA_READ_KEY_EXACT); - - if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) { - - if (dict_index_is_spatial(index)) { - /*Only min_key used in spatial index. */ - n_rows = rtr_estimate_n_rows_in_range( - index, range_start, mode1); - } else { - btr_pos_t tuple1(range_start, mode1, pages->first_page); - btr_pos_t tuple2(range_end, mode2, pages->last_page); - n_rows = btr_estimate_n_rows_in_range( - index, &tuple1, &tuple2); - pages->first_page= tuple1.page_id.raw(); - pages->last_page= tuple2.page_id.raw(); - } + if (!min_key) { + mode1 = PAGE_CUR_GE; + dtuple_set_n_fields(range_start, 0); + } else if (convert_search_mode_to_innobase(min_key->flag, mode1)) { + goto unsupported; } else { - - n_rows = HA_POS_ERROR; + dict_index_copy_types(range_start, index, key->ext_key_parts); + row_sel_convert_mysql_key_to_innobase( + range_start, + m_prebuilt->srch_key_val1, + m_prebuilt->srch_key_val_len, + index, min_key->key, min_key->length); + DBUG_ASSERT(range_start->n_fields > 0); } - mem_heap_free(heap); + if (!max_key) { + mode2 = PAGE_CUR_GE; + dtuple_set_n_fields(range_end, 0); + } else if (convert_search_mode_to_innobase(max_key->flag, mode2)) { + goto unsupported; + } else { + dict_index_copy_types(range_end, index, key->ext_key_parts); + row_sel_convert_mysql_key_to_innobase( + range_end, + m_prebuilt->srch_key_val2, + m_prebuilt->srch_key_val_len, + index, max_key->key, max_key->length); + DBUG_ASSERT(range_end->n_fields > 0); + } + + if (dict_index_is_spatial(index)) { + /*Only min_key used in spatial index. */ + n_rows = rtr_estimate_n_rows_in_range( + index, range_start, mode1); + } else { + btr_pos_t tuple1(range_start, mode1, pages->first_page); + btr_pos_t tuple2(range_end, mode2, pages->last_page); + n_rows = btr_estimate_n_rows_in_range(index, &tuple1, &tuple2); + pages->first_page= tuple1.page_id.raw(); + pages->last_page= tuple2.page_id.raw(); + } DBUG_EXECUTE_IF( "print_btr_estimate_n_rows_in_range_return_value", @@ -14294,11 +14306,7 @@ ha_innobase::records_in_range( (longlong) n_rows); ); -func_exit: - - m_prebuilt->trx->op_info = (char*)""; - - /* The MySQL optimizer seems to believe an estimate of 0 rows is + /* The MariaDB optimizer seems to believe an estimate of 0 rows is always accurate and may return the result 'Empty set' based on that. The accuracy is not guaranteed, and even if it were, for a locking read we should anyway perform the search to set the next-key lock. @@ -14308,6 +14316,10 @@ func_exit: n_rows = 1; } +unsupported: + mem_heap_free(heap); +func_exit: + m_prebuilt->trx->op_info = ""; DBUG_RETURN((ha_rows) n_rows); } diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 552f5714698..fb3a4f5fa07 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -1728,11 +1728,9 @@ instant_alter_column_possible( ut_ad(!is_null || nullable); n_nullable += nullable; n_add++; - uint l; + uint l = (*af)->pack_length(); switch ((*af)->type()) { case MYSQL_TYPE_VARCHAR: - l = reinterpret_cast - (*af)->get_length(); variable_length: if (l >= min_local_len) { max_size += blob_prefix @@ -1746,7 +1744,6 @@ instant_alter_column_possible( if (!is_null) { min_size += l; } - l = (*af)->pack_length(); max_size += l; lenlen += l > 255 ? 2 : 1; } @@ -1760,7 +1757,6 @@ instant_alter_column_possible( ((*af))->get_length(); goto variable_length; default: - l = (*af)->pack_length(); if (l > 255 && ib_table.not_redundant()) { goto variable_length; } diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index 4ec07b8158b..e77401ed9eb 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -24,6 +24,7 @@ Insert buffer Created 7/19/1997 Heikki Tuuri *******************************************************/ +#include #include "ibuf0ibuf.h" #include "btr0sea.h" @@ -1833,7 +1834,7 @@ corrupted: err = flst_add_last(ibuf_root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, - &mtr); + fil_system.sys_space->free_limit, &mtr); if (UNIV_UNLIKELY(err != DB_SUCCESS)) { goto corrupted; } @@ -1864,7 +1865,6 @@ Removes a page from the free list and frees it to the fsp system. */ static void ibuf_remove_free_page() { mtr_t mtr; - mtr_t mtr2; page_t* header_page; log_free_check(); @@ -1891,26 +1891,28 @@ early_exit: return; } - ibuf_mtr_start(&mtr2); - - buf_block_t* root = ibuf_tree_root_get(&mtr2); + buf_block_t* root = ibuf_tree_root_get(&mtr); if (UNIV_UNLIKELY(!root)) { - ibuf_mtr_commit(&mtr2); + goto early_exit; + } + + const auto root_savepoint = mtr.get_savepoint() - 1; + const uint32_t page_no = flst_get_last(PAGE_HEADER + + PAGE_BTR_IBUF_FREE_LIST + + root->page.frame).page; + + if (page_no >= fil_system.sys_space->free_limit) { goto early_exit; } mysql_mutex_unlock(&ibuf_mutex); - const uint32_t page_no = flst_get_last(PAGE_HEADER - + PAGE_BTR_IBUF_FREE_LIST - + root->page.frame).page; - /* NOTE that we must release the latch on the ibuf tree root because in fseg_free_page we access level 1 pages, and the root is a level 2 page. */ - - ibuf_mtr_commit(&mtr2); + root->page.lock.u_unlock(); + mtr.lock_register(root_savepoint, MTR_MEMO_BUF_FIX); ibuf_exit(&mtr); /* Since pessimistic inserts were prevented, we know that the @@ -1933,15 +1935,7 @@ early_exit: ibuf_enter(&mtr); mysql_mutex_lock(&ibuf_mutex); - - root = ibuf_tree_root_get(&mtr, &err); - if (UNIV_UNLIKELY(!root)) { - mysql_mutex_unlock(&ibuf_pessimistic_insert_mutex); - goto func_exit; - } - - ut_ad(page_no == flst_get_last(PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST - + root->page.frame).page); + mtr.upgrade_buffer_fix(root_savepoint, RW_X_LATCH); /* Remove the page from the free list and update the ibuf size data */ if (buf_block_t* block = @@ -1950,7 +1944,7 @@ early_exit: err = flst_remove(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, - &mtr); + fil_system.sys_space->free_limit, &mtr); } mysql_mutex_unlock(&ibuf_pessimistic_insert_mutex); @@ -2332,7 +2326,8 @@ func_exit: /** Merge the change buffer to some pages. */ static void ibuf_read_merge_pages(const uint32_t* space_ids, - const uint32_t* page_nos, ulint n_stored) + const uint32_t* page_nos, ulint n_stored, + bool slow_shutdown_cleanup) { for (ulint i = 0; i < n_stored; i++) { const uint32_t space_id = space_ids[i]; @@ -2357,30 +2352,28 @@ tablespace_deleted: if (UNIV_LIKELY(page_nos[i] < size)) { mtr.start(); dberr_t err; - buf_block_t *block = + /* Load the page and apply change buffers. */ + std::ignore = buf_page_get_gen(page_id_t(space_id, page_nos[i]), zip_size, RW_X_LATCH, nullptr, BUF_GET_POSSIBLY_FREED, &mtr, &err, true); - bool remove = !block - || fil_page_get_type(block->page.frame) - != FIL_PAGE_INDEX - || !page_is_leaf(block->page.frame); mtr.commit(); if (err == DB_TABLESPACE_DELETED) { s->x_unlock(); goto tablespace_deleted; } - if (!remove) { - s->x_unlock(); - continue; - } } s->x_unlock(); - if (srv_shutdown_state == SRV_SHUTDOWN_NONE - || srv_fast_shutdown) { + /* During slow shutdown cleanup, we apply all pending IBUF + changes and need to cleanup any left-over IBUF records. There + are a few cases when the changes are already discarded and IBUF + bitmap is cleaned but we miss to delete the record. Even after + the issues are fixed, we need to keep this safety measure for + upgraded DBs with such left over records. */ + if (!slow_shutdown_cleanup) { continue; } @@ -2451,7 +2444,7 @@ ATTRIBUTE_COLD ulint ibuf_contract() space_ids, page_nos, &n_pages); ibuf_mtr_commit(&mtr); - ibuf_read_merge_pages(space_ids, page_nos, n_pages); + ibuf_read_merge_pages(space_ids, page_nos, n_pages, true); return(sum_sizes + 1); } @@ -2532,7 +2525,7 @@ ibuf_merge_space( } #endif /* UNIV_DEBUG */ - ibuf_read_merge_pages(spaces, pages, n_pages); + ibuf_read_merge_pages(spaces, pages, n_pages, false); } return(n_pages); diff --git a/storage/innobase/include/btr0pcur.h b/storage/innobase/include/btr0pcur.h index c66a3bfa329..5f84328da19 100644 --- a/storage/innobase/include/btr0pcur.h +++ b/storage/innobase/include/btr0pcur.h @@ -28,7 +28,6 @@ Created 2/23/1996 Heikki Tuuri #include "dict0dict.h" #include "btr0cur.h" -#include "buf0block_hint.h" #include "btr0btr.h" #include "gis0rtree.h" @@ -332,8 +331,8 @@ struct btr_pcur_t /** BTR_PCUR_ON, BTR_PCUR_BEFORE, or BTR_PCUR_AFTER, depending on whether cursor was on, before, or after the old_rec record */ btr_pcur_pos_t rel_pos= btr_pcur_pos_t(0); - /** buffer block when the position was stored */ - buf::Block_hint block_when_stored; + /** the page identifier of old_rec */ + page_id_t old_page_id{0,0}; /** the modify clock value of the buffer block when the cursor position was stored */ ib_uint64_t modify_clock= 0; @@ -432,7 +431,8 @@ btr_pcur_open( } /** Open a cursor on the first user record satisfying the search condition; -in case of no match, after the last index record. */ +in case of no match, after the last index record. +@return DB_SUCCESS or error code */ MY_ATTRIBUTE((nonnull, warn_unused_result)) inline dberr_t diff --git a/storage/innobase/include/buf0block_hint.h b/storage/innobase/include/buf0block_hint.h deleted file mode 100644 index d4fee7c1e99..00000000000 --- a/storage/innobase/include/buf0block_hint.h +++ /dev/null @@ -1,76 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2020, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2020, MariaDB Corporation. -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License, version 2.0, as published by the -Free Software Foundation. - -This program is also distributed with certain software (including but not -limited to OpenSSL) that is licensed under separate terms, as designated in a -particular file or component or in included license documentation. The authors -of MySQL hereby grant you an additional permission to link the program and -your derivative works with the separately licensed software that they have -included with MySQL. - -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, version 2.0, -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 - -*****************************************************************************/ -#pragma once -#include "buf0buf.h" - -namespace buf { -class Block_hint { -public: - /** Stores the pointer to the block, which is currently buffer-fixed. - @param block a pointer to a buffer-fixed block to be stored */ - inline void store(buf_block_t *block) - { - ut_ad(block->page.buf_fix_count()); - m_block= block; - m_page_id= block->page.id(); - } - - /** Clears currently stored pointer. */ - inline void clear() { m_block= nullptr; } - - /** Invoke f on m_block(which may be null) - @param f The function to be executed. It will be passed the pointer. - If you wish to use the block pointer subsequently, - you need to ensure you buffer-fix it before returning from f. - @return the return value of f - */ - template - bool run_with_hint(const F &f) - { - buffer_fix_block_if_still_valid(); - /* m_block could be changed during f() call, so we use local - variable to remember which block we need to unfix */ - buf_block_t *block= m_block; - bool res= f(block); - if (block) - block->page.unfix(); - return res; - } - - buf_block_t *block() const { return m_block; } - - private: - /** The block pointer stored by store(). */ - buf_block_t *m_block= nullptr; - /** If m_block is non-null, the m_block->page.id at time it was stored. */ - page_id_t m_page_id{0, 0}; - - /** A helper function which checks if m_block is not a dangling pointer and - still points to block with page with m_page_id and if so, buffer-fixes it, - otherwise clear()s it */ - void buffer_fix_block_if_still_valid(); -}; -} // namespace buf diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index b909738875b..c291615cf37 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -158,14 +158,25 @@ buf_block_free( #define buf_page_get(ID, SIZE, LA, MTR) \ buf_page_get_gen(ID, SIZE, LA, NULL, BUF_GET, MTR) -/** Try to acquire a page latch. -@param rw_latch RW_S_LATCH or RW_X_LATCH +/** Try to buffer-fix a page. @param block guessed block +@param id expected block->page.id() +@return block if it was buffer-fixed +@retval nullptr if the block no longer is valid */ +buf_block_t *buf_page_optimistic_fix(buf_block_t *block, page_id_t id) + MY_ATTRIBUTE((nonnull, warn_unused_result)); + +/** Try to acquire a page latch after buf_page_optimistic_fix(). +@param block buffer-fixed block +@param rw_latch RW_S_LATCH or RW_X_LATCH @param modify_clock expected value of block->modify_clock @param mtr mini-transaction -@return whether the latch was acquired (the page is an allocated file page) */ -bool buf_page_optimistic_get(ulint rw_latch, buf_block_t *block, - uint64_t modify_clock, mtr_t *mtr); +@return block if the latch was acquired +@retval nullptr if block->unfix() was called because it no longer is valid */ +buf_block_t *buf_page_optimistic_get(buf_block_t *block, + rw_lock_type_t rw_latch, + uint64_t modify_clock, mtr_t *mtr) + MY_ATTRIBUTE((nonnull, warn_unused_result)); /** Try to S-latch a page. Suitable for using when holding the lock_sys latches (as it avoids deadlock). @@ -290,15 +301,6 @@ on the block. */ UNIV_INLINE void buf_block_modify_clock_inc( -/*=======================*/ - buf_block_t* block); /*!< in: block */ -/********************************************************************//** -Returns the value of the modify clock. The caller must have an s-lock -or x-lock on the block. -@return value */ -UNIV_INLINE -ib_uint64_t -buf_block_get_modify_clock( /*=======================*/ buf_block_t* block); /*!< in: block */ #endif /* !UNIV_INNOCHECKSUM */ diff --git a/storage/innobase/include/buf0buf.inl b/storage/innobase/include/buf0buf.inl index b3158cf1680..050c8493634 100644 --- a/storage/innobase/include/buf0buf.inl +++ b/storage/innobase/include/buf0buf.inl @@ -116,17 +116,3 @@ buf_block_modify_clock_inc( block->modify_clock++; } - -/********************************************************************//** -Returns the value of the modify clock. The caller must have an s-lock -or x-lock on the block. -@return value */ -UNIV_INLINE -ib_uint64_t -buf_block_get_modify_clock( -/*=======================*/ - buf_block_t* block) /*!< in: block */ -{ - ut_ad(block->page.lock.have_any()); - return(block->modify_clock); -} diff --git a/storage/innobase/include/data0data.h b/storage/innobase/include/data0data.h index a5356e0d1a3..fcb543ebb1a 100644 --- a/storage/innobase/include/data0data.h +++ b/storage/innobase/include/data0data.h @@ -339,15 +339,12 @@ dtuple_set_types_binary( dtuple_t* tuple, /*!< in: data tuple */ ulint n) /*!< in: number of fields to set */ MY_ATTRIBUTE((nonnull)); -/**********************************************************************//** -Checks if a dtuple contains an SQL null value. -@return TRUE if some field is SQL null */ +/** Checks if a dtuple contains an SQL null value. +@param tuple tuple +@param fields_number number of fields in the tuple to check +@return true if some field is SQL null */ UNIV_INLINE -ibool -dtuple_contains_null( -/*=================*/ - const dtuple_t* tuple) /*!< in: dtuple */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); +bool dtuple_contains_null(const dtuple_t *tuple, ulint fields_number = 0); /**********************************************************//** Checks that a data field is typed. Asserts an error if not. @return TRUE if ok */ diff --git a/storage/innobase/include/data0data.inl b/storage/innobase/include/data0data.inl index 2d1bf5a2d50..b6c6ace8dc0 100644 --- a/storage/innobase/include/data0data.inl +++ b/storage/innobase/include/data0data.inl @@ -596,28 +596,18 @@ data_write_sql_null( memset(data, 0, len); } -/**********************************************************************//** -Checks if a dtuple contains an SQL null value. -@return TRUE if some field is SQL null */ +/** Checks if a dtuple contains an SQL null value. +@param tuple tuple +@param fields_number number of fields in the tuple to check +@return true if some field is SQL null */ UNIV_INLINE -ibool -dtuple_contains_null( -/*=================*/ - const dtuple_t* tuple) /*!< in: dtuple */ +bool dtuple_contains_null(const dtuple_t *tuple, ulint fields_number) { - ulint n; - ulint i; - - n = dtuple_get_n_fields(tuple); - - for (i = 0; i < n; i++) { - if (dfield_is_null(dtuple_get_nth_field(tuple, i))) { - - return(TRUE); - } - } - - return(FALSE); + ulint n= fields_number ? fields_number : dtuple_get_n_fields(tuple); + for (ulint i= 0; i < n; i++) + if (dfield_is_null(dtuple_get_nth_field(tuple, i))) + return true; + return false; } /**************************************************************//** diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 4714b71619d..0268a28021f 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -1010,8 +1010,6 @@ struct dict_index_t { /*!< number of columns the user defined to be in the index: in the internal representation we add more columns */ - unsigned nulls_equal:1; - /*!< if true, SQL NULL == SQL NULL */ unsigned n_uniq:10;/*!< number of fields from the beginning which are enough to determine an index entry uniquely */ diff --git a/storage/innobase/include/dict0mem.inl b/storage/innobase/include/dict0mem.inl index d60ee5d9bf4..edb7cf92cd5 100644 --- a/storage/innobase/include/dict0mem.inl +++ b/storage/innobase/include/dict0mem.inl @@ -63,6 +63,5 @@ dict_mem_fill_index_struct( & index->MAX_N_FIELDS; /* The '1 +' above prevents allocation of an empty mem block */ - index->nulls_equal = false; ut_d(index->magic_n = DICT_INDEX_MAGIC_N); } diff --git a/storage/innobase/include/dyn0buf.h b/storage/innobase/include/dyn0buf.h index c2fc93c4cf3..7a4e6760019 100644 --- a/storage/innobase/include/dyn0buf.h +++ b/storage/innobase/include/dyn0buf.h @@ -149,8 +149,7 @@ public: /** Storage */ byte m_data[MAX_DATA_SIZE]; - /** number of data bytes used in this block; - DYN_BLOCK_FULL_FLAG is set when the block becomes full */ + /** number of data bytes used in this block */ uint32_t m_used; friend class mtr_buf_t; diff --git a/storage/innobase/include/dyn0types.h b/storage/innobase/include/dyn0types.h index 83d0b0d64c2..af7f663d970 100644 --- a/storage/innobase/include/dyn0types.h +++ b/storage/innobase/include/dyn0types.h @@ -33,7 +33,4 @@ Created 2013-03-16 Sunny Bains /** This is the initial 'payload' size of a dynamic array */ #define DYN_ARRAY_DATA_SIZE 512 -/** Flag for dyn_block_t::used that indicates a full block */ -#define DYN_BLOCK_FULL_FLAG 0x1000000UL - #endif /* dyn0types_h */ diff --git a/storage/innobase/include/fut0lst.h b/storage/innobase/include/fut0lst.h index 746dab80400..1adec365f2b 100644 --- a/storage/innobase/include/fut0lst.h +++ b/storage/innobase/include/fut0lst.h @@ -78,34 +78,40 @@ void flst_init(const buf_block_t &block, byte *base, mtr_t *mtr) MY_ATTRIBUTE((nonnull)); /** Append a file list node to a list. -@param[in,out] base base node block -@param[in] boffset byte offset of the base node -@param[in,out] add block to be added -@param[in] aoffset byte offset of the node to be added -@param[in,out] mtr mini-transaction +@param base base node block +@param boffset byte offset of the base node +@param add block to be added +@param aoffset byte offset of the node to be added +@param limit fil_space_t::free_limit +@param mtr mini-transaction @return error code */ dberr_t flst_add_last(buf_block_t *base, uint16_t boffset, - buf_block_t *add, uint16_t aoffset, mtr_t *mtr) + buf_block_t *add, uint16_t aoffset, + uint32_t limit, mtr_t *mtr) MY_ATTRIBUTE((nonnull, warn_unused_result)); /** Prepend a file list node to a list. -@param[in,out] base base node block -@param[in] boffset byte offset of the base node -@param[in,out] add block to be added -@param[in] aoffset byte offset of the node to be added -@param[in,out] mtr mini-transaction +@param base base node block +@param boffset byte offset of the base node +@param add block to be added +@param aoffset byte offset of the node to be added +@param limit fil_space_t::free_limit +@param mtr mini-transaction @return error code */ dberr_t flst_add_first(buf_block_t *base, uint16_t boffset, - buf_block_t *add, uint16_t aoffset, mtr_t *mtr) + buf_block_t *add, uint16_t aoffset, + uint32_t limit, mtr_t *mtr) MY_ATTRIBUTE((nonnull, warn_unused_result)); /** Remove a file list node. -@param[in,out] base base node block -@param[in] boffset byte offset of the base node -@param[in,out] cur block to be removed -@param[in] coffset byte offset of the current record to be removed -@param[in,out] mtr mini-transaction +@param base base node block +@param boffset byte offset of the base node +@param cur block to be removed +@param coffset byte offset of the current record to be removed +@param limit fil_space_t::free_limit +@param mtr mini-transaction @return error code */ dberr_t flst_remove(buf_block_t *base, uint16_t boffset, - buf_block_t *cur, uint16_t coffset, mtr_t *mtr) + buf_block_t *cur, uint16_t coffset, + uint32_t limit, mtr_t *mtr) MY_ATTRIBUTE((nonnull, warn_unused_result)); /** @return the length of a list */ @@ -117,11 +123,9 @@ inline uint32_t flst_get_len(const flst_base_node_t *base) /** @return a file address */ inline fil_addr_t flst_read_addr(const byte *faddr) { - fil_addr_t addr= { mach_read_from_4(faddr + FIL_ADDR_PAGE), - mach_read_from_2(faddr + FIL_ADDR_BYTE) }; - ut_a(addr.page == FIL_NULL || addr.boffset >= FIL_PAGE_DATA); - ut_a(ut_align_offset(faddr, srv_page_size) >= FIL_PAGE_DATA); - return addr; + ut_ad(ut_align_offset(faddr, srv_page_size) >= FIL_PAGE_DATA); + return fil_addr_t{mach_read_from_4(faddr + FIL_ADDR_PAGE), + mach_read_from_2(faddr + FIL_ADDR_BYTE)}; } /** @return list first node address */ diff --git a/storage/innobase/include/gis0type.h b/storage/innobase/include/gis0type.h index d6a4ef67a38..2dc25a898b7 100644 --- a/storage/innobase/include/gis0type.h +++ b/storage/innobase/include/gis0type.h @@ -66,10 +66,7 @@ typedef std::vector > rtr_rec_vector; /* Structure for matched records on the leaf page */ typedef struct matched_rec { - byte* bufp; /*!< aligned buffer point */ - byte rec_buf[UNIV_PAGE_SIZE_MAX * 2]; - /*!< buffer used to copy matching rec */ - buf_block_t block; /*!< the shadow buffer block */ + buf_block_t* block; /*!< the shadow buffer block */ ulint used; /*!< memory used */ rtr_rec_vector* matched_recs; /*!< vector holding the matching rec */ mysql_mutex_t rtr_match_mutex;/*!< mutex protect the match_recs @@ -107,7 +104,6 @@ typedef struct rtr_info{ /*!< mutex protect the "path" vector */ rtr_mbr_t mbr; /*!< the search MBR */ que_thr_t* thr; /*!< the search thread */ - mem_heap_t* heap; /*!< memory heap */ btr_cur_t* cursor; /*!< cursor used for search */ dict_index_t* index; /*!< index it is searching */ bool need_prdt_lock; diff --git a/storage/innobase/include/row0sel.h b/storage/innobase/include/row0sel.h index 8134c60fe72..54e4a1d283f 100644 --- a/storage/innobase/include/row0sel.h +++ b/storage/innobase/include/row0sel.h @@ -115,8 +115,8 @@ row_sel_convert_mysql_key_to_innobase( ulint buf_len, /*!< in: buffer length */ dict_index_t* index, /*!< in: index of the key value */ const byte* key_ptr, /*!< in: MySQL key value */ - ulint key_len); /*!< in: MySQL key value length */ - + ulint key_len) /*!< in: MySQL key value length */ + MY_ATTRIBUTE((nonnull(1,4,5))); /** Search for rows in the database using cursor. Function is mainly used for tables that are shared across connections and diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h index 0f4f8afa15b..1fb6cd68538 100644 --- a/storage/innobase/include/trx0purge.h +++ b/storage/innobase/include/trx0purge.h @@ -55,80 +55,74 @@ Run a purge batch. @return number of undo log pages handled in the batch */ ulint trx_purge(ulint n_tasks, ulint history_size); -/** Rollback segements from a given transaction with trx-no -scheduled for purge. */ -class TrxUndoRsegs { -private: - typedef std::vector > - trx_rsegs_t; -public: - typedef trx_rsegs_t::iterator iterator; - typedef trx_rsegs_t::const_iterator const_iterator; - - TrxUndoRsegs() = default; - - /** Constructor */ - TrxUndoRsegs(trx_rseg_t& rseg) - : trx_no(rseg.last_trx_no()), m_rsegs(1, &rseg) {} - /** Constructor */ - TrxUndoRsegs(trx_id_t trx_no, trx_rseg_t& rseg) - : trx_no(trx_no), m_rsegs(1, &rseg) {} - - bool operator!=(const TrxUndoRsegs& other) const - { return trx_no != other.trx_no; } - bool empty() const { return m_rsegs.empty(); } - void erase(iterator& it) { m_rsegs.erase(it); } - iterator begin() { return(m_rsegs.begin()); } - iterator end() { return(m_rsegs.end()); } - const_iterator begin() const { return m_rsegs.begin(); } - const_iterator end() const { return m_rsegs.end(); } - - /** Compare two TrxUndoRsegs based on trx_no. - @param elem1 first element to compare - @param elem2 second element to compare - @return true if elem1 > elem2 else false.*/ - bool operator()(const TrxUndoRsegs& lhs, const TrxUndoRsegs& rhs) - { - return(lhs.trx_no > rhs.trx_no); - } - - /** Copy of trx_rseg_t::last_trx_no() */ - trx_id_t trx_no= 0; -private: - /** Rollback segments of a transaction, scheduled for purge. */ - trx_rsegs_t m_rsegs{}; -}; - -typedef std::priority_queue< - TrxUndoRsegs, - std::vector >, - TrxUndoRsegs> purge_pq_t; - -/** Chooses the rollback segment with the oldest committed transaction */ -struct TrxUndoRsegsIterator { - /** Constructor */ - TrxUndoRsegsIterator(); - /** Sets the next rseg to purge in purge_sys. - Executed in the purge coordinator thread. - @retval false when nothing is to be purged - @retval true when purge_sys.rseg->latch was locked */ - inline bool set_next(); - -private: - // Disable copying - TrxUndoRsegsIterator(const TrxUndoRsegsIterator&); - TrxUndoRsegsIterator& operator=(const TrxUndoRsegsIterator&); - - /** The current element to process */ - TrxUndoRsegs m_rsegs; - /** Track the current element in m_rsegs */ - TrxUndoRsegs::const_iterator m_iter; -}; - /** The control structure used in the purge operation */ class purge_sys_t { - friend TrxUndoRsegsIterator; + /** Min-heap based priority queue of (trx_no, trx_sys.rseg_array index) + pairs, ordered on trx_no. The highest 64-TRX_NO_SHIFT bits of each element is + trx_no, the lowest 8 bits is rseg's index in trx_sys.rseg_array. */ + class purge_queue + { + public: + typedef std::vector> container_type; + /** Number of bits reseved to shift trx_no in purge queue element */ + static constexpr unsigned TRX_NO_SHIFT= 8; + + bool empty() const { return m_array.empty(); } + void clear() { m_array.clear(); } + + /** Push (trx_no, trx_sys.rseg_array index) into min-heap. + @param trx_no_rseg (trx_no << TRX_NO_SHIFT | (trx_sys.rseg_array index)) */ + void push_trx_no_rseg(container_type::value_type trx_no_rseg) + { + m_array.push_back(trx_no_rseg); + std::push_heap(m_array.begin(), m_array.end(), + std::greater()); + } + + /** Push rseg to priority queue. + @param trx_no trx_no of committed transaction + @param rseg rseg of committed transaction*/ + void push(trx_id_t trx_no, const trx_rseg_t &rseg) + { + ut_ad(trx_no < 1ULL << (DATA_TRX_ID_LEN * CHAR_BIT)); + ut_ad(&rseg >= trx_sys.rseg_array); + ut_ad(&rseg < trx_sys.rseg_array + TRX_SYS_N_RSEGS); + push_trx_no_rseg(trx_no << TRX_NO_SHIFT | + byte(&rseg - trx_sys.rseg_array)); + } + + /** Extracts rseg from (trx_no, trx_sys.rseg_array index) pair. + @param trx_no_rseg (trx_no << TRX_NO_SHIFT | (trx_sys.rseg_array index) + @return pointer to rseg in trx_sys.rseg_array */ + static trx_rseg_t *rseg(container_type::value_type trx_no_rseg) { + byte i= static_cast(trx_no_rseg); + ut_ad(i < TRX_SYS_N_RSEGS); + return &trx_sys.rseg_array[i]; + } + + /** Pop rseg from priority queue. + @return pointer to popped trx_rseg_t object */ + trx_rseg_t *pop() + { + ut_ad(!empty()); + std::pop_heap(m_array.begin(), m_array.end(), + std::greater()); + trx_rseg_t *r = rseg(m_array.back()); + m_array.pop_back(); + return r; + } + + /** Clone m_array. + @return m_array clone */ + container_type clone_container() const{ return m_array; } + + private: + /** Array of (trx_no, trx_sys.rseg_array index) pairs. */ + container_type m_array; + }; + + public: /** latch protecting view, m_enabled */ alignas(CPU_LEVEL1_DCACHE_LINESIZE) mutable srw_spin_lock latch; @@ -244,15 +238,36 @@ private: record */ uint16_t hdr_offset; /*!< Header byte offset on the page */ + /** Binary min-heap of (trx_no, trx_sys.rseg_array index) pairs, ordered on + trx_no. It is protected by the pq_mutex */ + purge_queue purge_queue; + + /** Mutex protecting purge_queue */ + mysql_mutex_t pq_mutex; - TrxUndoRsegsIterator - rseg_iter; /*!< Iterator to get the next rseg - to process */ public: - purge_pq_t purge_queue; /*!< Binary min-heap, ordered on - TrxUndoRsegs::trx_no. It is protected - by the pq_mutex */ - mysql_mutex_t pq_mutex; /*!< Mutex protecting purge_queue */ + + void enqueue(trx_id_t trx_no, const trx_rseg_t &rseg) { + mysql_mutex_assert_owner(&pq_mutex); + purge_queue.push(trx_no, rseg); + } + + /** Push to purge queue without acquiring pq_mutex. + @param rseg rseg to push */ + void enqueue(const trx_rseg_t &rseg) { enqueue(rseg.last_trx_no(), rseg); } + + /** Clone purge queue container. + @return purge queue container clone */ + purge_queue::container_type clone_queue_container() const { + mysql_mutex_assert_owner(&pq_mutex); + return purge_queue.clone_container(); + } + + /** Acquare purge_queue_mutex */ + void queue_lock() { mysql_mutex_lock(&pq_mutex); } + + /** Release purge queue mutex */ + void queue_unlock() { mysql_mutex_unlock(&pq_mutex); } /** innodb_undo_log_truncate=ON state; only modified by purge_coordinator_callback() */ @@ -332,8 +347,9 @@ private: /** Update the last not yet purged history log info in rseg when we have purged a whole undo log. Advances also purge_trx_no - past the purged log. */ - void rseg_get_next_history_log(); + past the purged log. + @return whether anything is to be purged */ + bool rseg_get_next_history_log(); public: /** @@ -438,6 +454,11 @@ public: @param already_stopped True indicates purge threads were already stopped */ void stop_FTS(const dict_table_t &table, bool already_stopped=false); + + /** Cleanse purge queue to remove the rseg that reside in undo-tablespace + marked for truncate. + @param space undo tablespace being truncated */ + void cleanse_purge_queue(const fil_space_t &space); }; /** The global data structure coordinating a purge */ diff --git a/storage/innobase/include/trx0rseg.h b/storage/innobase/include/trx0rseg.h index 5df59863f32..e0051b2a1d0 100644 --- a/storage/innobase/include/trx0rseg.h +++ b/storage/innobase/include/trx0rseg.h @@ -170,19 +170,21 @@ public: /** Last not yet purged undo log header; FIL_NULL if all purged */ uint32_t last_page_no; - /** trx_t::no | last_offset << 48 */ + /** trx_t::no << 16 | last_offset */ uint64_t last_commit_and_offset; /** @return the commit ID of the last committed transaction */ trx_id_t last_trx_no() const - { return last_commit_and_offset & ((1ULL << 48) - 1); } + { return last_commit_and_offset >> 16; } /** @return header offset of the last committed transaction */ uint16_t last_offset() const - { return static_cast(last_commit_and_offset >> 48); } + { + return static_cast(last_commit_and_offset); + } void set_last_commit(uint16_t last_offset, trx_id_t trx_no) { - last_commit_and_offset= static_cast(last_offset) << 48 | trx_no; + last_commit_and_offset= trx_no << 16 | static_cast(last_offset); } /** @return the page identifier */ diff --git a/storage/innobase/include/trx0undo.inl b/storage/innobase/include/trx0undo.inl index 9f05989f634..023e2b98fb2 100644 --- a/storage/innobase/include/trx0undo.inl +++ b/storage/innobase/include/trx0undo.inl @@ -125,5 +125,6 @@ trx_undo_page_get_next_rec(const buf_block_t *undo_page, uint16_t rec, { uint16_t end= trx_undo_page_get_end(undo_page, page_no, offset); uint16_t next= mach_read_from_2(undo_page->page.frame + rec); - return next == end ? nullptr : undo_page->page.frame + next; + ut_ad(next <= end); + return next >= end ? nullptr : undo_page->page.frame + next; } diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 69b3dd1f5c2..a210700727c 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -5586,47 +5586,43 @@ lock_rec_insert_check_and_lock( return err; } -/*********************************************************************//** -Creates an explicit record lock for a running transaction that currently only -has an implicit lock on the record. The transaction instance must have a -reference count > 0 so that it can't be committed and freed before this -function has completed. */ -static -bool -lock_rec_convert_impl_to_expl_for_trx( -/*==================================*/ - trx_t* trx, /*!< in/out: active transaction */ - const page_id_t id, /*!< in: page identifier */ - const rec_t* rec, /*!< in: user record on page */ - dict_index_t* index) /*!< in: index of record */ +/** Create an explicit record lock for a transaction that currently only +has an implicit lock on the record. +@param trx referenced, active transaction, or nullptr +@param id page identifier +@param rec record in the page +@param index the index B-tree that the record belongs to +@return trx, with the reference released */ +static trx_t *lock_rec_convert_impl_to_expl_for_trx(trx_t *trx, + const page_id_t id, + const rec_t *rec, + dict_index_t *index) { - if (!trx) - return false; - - ut_ad(trx->is_referenced()); - ut_ad(page_rec_is_leaf(rec)); - ut_ad(!rec_is_metadata(rec, *index)); - - DEBUG_SYNC_C("before_lock_rec_convert_impl_to_expl_for_trx"); - ulint heap_no= page_rec_get_heap_no(rec); - + if (trx) { - LockGuard g{lock_sys.rec_hash, id}; - trx->mutex_lock(); - ut_ad(!trx_state_eq(trx, TRX_STATE_NOT_STARTED)); + ut_ad(trx->is_referenced()); + ut_ad(page_rec_is_leaf(rec)); + ut_ad(!rec_is_metadata(rec, *index)); - if (!trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY) && - !lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, g.cell(), id, heap_no, - trx)) - lock_rec_add_to_queue(LOCK_X | LOCK_REC_NOT_GAP, g.cell(), id, - page_align(rec), heap_no, index, trx, true); + ulint heap_no= page_rec_get_heap_no(rec); + + { + LockGuard g{lock_sys.rec_hash, id}; + trx->mutex_lock(); + ut_ad(!trx_state_eq(trx, TRX_STATE_NOT_STARTED)); + + if (!trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY) && + !lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, g.cell(), id, heap_no, + trx)) + lock_rec_add_to_queue(LOCK_X | LOCK_REC_NOT_GAP, g.cell(), id, + page_align(rec), heap_no, index, trx, true); + } + + trx->release_reference(); + trx->mutex_unlock(); } - trx->mutex_unlock(); - trx->release_reference(); - - DEBUG_SYNC_C("after_lock_rec_convert_impl_to_expl_for_trx"); - return false; + return trx; } @@ -5717,10 +5713,11 @@ should be created. @param[in] rec record on the leaf page @param[in] index the index of the record @param[in] offsets rec_get_offsets(rec,index) -@return whether caller_trx already holds an exclusive lock on rec */ +@return unsafe pointer to a transaction that held an exclusive lock on rec +@retval nullptr if no transaction held an exclusive lock */ template static -bool +const trx_t * lock_rec_convert_impl_to_expl( trx_t* caller_trx, page_id_t id, @@ -5744,10 +5741,10 @@ lock_rec_convert_impl_to_expl( trx_id = lock_clust_rec_some_has_impl(rec, index, offsets); if (trx_id == 0) { - return false; + return nullptr; } if (UNIV_UNLIKELY(trx_id == caller_trx->id)) { - return true; + return caller_trx; } trx = trx_sys.find(caller_trx, trx_id); @@ -5758,7 +5755,7 @@ lock_rec_convert_impl_to_expl( offsets); if (trx == caller_trx) { trx->release_reference(); - return true; + return trx; } ut_d(lock_rec_other_trx_holds_expl(caller_trx, trx, rec, id)); @@ -5803,11 +5800,18 @@ lock_clust_rec_modify_check_and_lock( /* If a transaction has no explicit x-lock set on the record, set one for it */ - if (lock_rec_convert_impl_to_expl(thr_get_trx(thr), - block->page.id(), + trx_t *trx = thr_get_trx(thr); + if (const trx_t *owner = + lock_rec_convert_impl_to_expl(trx, block->page.id(), rec, index, offsets)) { - /* We already hold an implicit exclusive lock. */ - return DB_SUCCESS; + if (owner == trx) { + /* We already hold an exclusive lock. */ + return DB_SUCCESS; + } + + if (trx->snapshot_isolation && trx->read_view.is_open()) { + return DB_RECORD_CHANGED; + } } err = lock_rec_lock(true, LOCK_X | LOCK_REC_NOT_GAP, @@ -5970,12 +5974,19 @@ lock_sec_rec_read_check_and_lock( return DB_SUCCESS; } - if (!page_rec_is_supremum(rec) - && lock_rec_convert_impl_to_expl( - trx, block->page.id(), rec, index, offsets) - && gap_mode == LOCK_REC_NOT_GAP) { - /* We already hold an implicit exclusive lock. */ - return DB_SUCCESS; + if (page_rec_is_supremum(rec)) { + } else if (const trx_t *owner = + lock_rec_convert_impl_to_expl(trx, block->page.id(), + rec, index, offsets)) { + if (owner == trx) { + if (gap_mode == LOCK_REC_NOT_GAP) { + /* We already hold an exclusive lock. */ + return DB_SUCCESS; + } + } else if (trx->snapshot_isolation + && trx->read_view.is_open()) { + return DB_RECORD_CHANGED; + } } #ifdef WITH_WSREP @@ -6055,13 +6066,20 @@ lock_clust_rec_read_check_and_lock( ulint heap_no = page_rec_get_heap_no(rec); trx_t *trx = thr_get_trx(thr); - if (!lock_table_has(trx, index->table, LOCK_X) - && heap_no != PAGE_HEAP_NO_SUPREMUM - && lock_rec_convert_impl_to_expl(trx, id, - rec, index, offsets) - && gap_mode == LOCK_REC_NOT_GAP) { - /* We already hold an implicit exclusive lock. */ - return DB_SUCCESS; + if (lock_table_has(trx, index->table, LOCK_X) + || heap_no == PAGE_HEAP_NO_SUPREMUM) { + } else if (const trx_t *owner = + lock_rec_convert_impl_to_expl(trx, id, + rec, index, offsets)) { + if (owner == trx) { + if (gap_mode == LOCK_REC_NOT_GAP) { + /* We already hold an exclusive lock. */ + return DB_SUCCESS; + } + } else if (trx->snapshot_isolation + && trx->read_view.is_open()) { + return DB_RECORD_CHANGED; + } } if (heap_no > PAGE_HEAP_NO_SUPREMUM && gap_mode != LOCK_GAP diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index c9325b8df79..abeecbd48ba 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -1513,7 +1513,7 @@ void mtr_t::upgrade_buffer_fix(ulint savepoint, rw_lock_type_t rw_latch) ut_ad(slot.type == MTR_MEMO_BUF_FIX); buf_block_t *block= static_cast(slot.object); ut_d(const auto state= block->page.state()); - ut_ad(state > buf_page_t::UNFIXED); + ut_ad(state > buf_page_t::FREED); ut_ad(state > buf_page_t::WRITE_FIX || state < buf_page_t::READ_FIX); static_assert(int{MTR_MEMO_PAGE_S_FIX} == int{RW_S_LATCH}, ""); static_assert(int{MTR_MEMO_PAGE_X_FIX} == int{RW_X_LATCH}, ""); diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 408c6b39a7c..6194e9c3eec 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -1855,14 +1855,39 @@ PageConverter::update_records( bool clust_index = m_index->m_srv_index == m_cluster_index; /* This will also position the cursor on the first user record. */ + rec_t* rec = m_rec_iter.open(block, m_index->m_srv_index); - if (!m_rec_iter.open(block, m_index->m_srv_index)) { + if (!rec) { return DB_CORRUPTION; } + ulint deleted; + + if (!page_has_prev(block->page.frame) + && m_index->m_srv_index->is_instant()) { + /* Expect to find the hidden metadata record */ + if (page_rec_is_supremum(rec)) { + return DB_CORRUPTION; + } + + const ulint info_bits = rec_get_info_bits(rec, comp); + + if (!(info_bits & REC_INFO_MIN_REC_FLAG)) { + return DB_CORRUPTION; + } + + if (!(info_bits & REC_INFO_DELETED_FLAG) + != !m_index->m_srv_index->table->instant) { + return DB_CORRUPTION; + } + + deleted = 0; + goto first; + } + while (!m_rec_iter.end()) { - rec_t* rec = m_rec_iter.current(); - ibool deleted = rec_get_deleted_flag(rec, comp); + rec = m_rec_iter.current(); + deleted = rec_get_deleted_flag(rec, comp); /* For the clustered index we have to adjust the BLOB reference and the system fields irrespective of the @@ -1870,6 +1895,7 @@ PageConverter::update_records( cluster records is required for purge to work later. */ if (deleted || clust_index) { +first: m_offsets = rec_get_offsets( rec, m_index->m_srv_index, m_offsets, m_index->m_srv_index->n_core_fields, @@ -3298,7 +3324,7 @@ static dict_table_t *build_fts_hidden_table( return new_table; } -/* find, parse instant metadata, performing variaous checks, +/* find, parse instant metadata, performing various checks, and apply it to dict_table_t @return DB_SUCCESS or some error */ static dberr_t handle_instant_metadata(dict_table_t *table, diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 5c79f56607c..b022636f9b5 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -2000,7 +2000,7 @@ row_ins_dupl_error_with_rec( /* In a unique secondary index we allow equal key values if they contain SQL NULLs */ - if (!dict_index_is_clust(index) && !index->nulls_equal) { + if (!dict_index_is_clust(index)) { for (i = 0; i < n_unique; i++) { if (dfield_is_null(dtuple_get_nth_field(entry, i))) { @@ -2102,16 +2102,8 @@ row_ins_scan_sec_index_for_duplicate( /* If the secondary index is unique, but one of the fields in the n_unique first fields is NULL, a unique key violation cannot occur, since we define NULL != NULL in this case */ - - if (!index->nulls_equal) { - for (ulint i = 0; i < n_unique; i++) { - if (UNIV_SQL_NULL == dfield_get_len( - dtuple_get_nth_field(entry, i))) { - - DBUG_RETURN(DB_SUCCESS); - } - } - } + if (index->n_nullable && dtuple_contains_null(entry, n_unique)) + DBUG_RETURN(DB_SUCCESS); /* Store old value on n_fields_cmp */ diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 79c70fbb78b..944f73588ae 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -1189,11 +1189,11 @@ sel_set_rtr_rec_lock( ut_ad(page_align(first_rec) == cur_block->page.frame); ut_ad(match->valid); - match->block.page.lock.x_lock(); + match->block->page.lock.x_lock(); retry: cur_block = btr_pcur_get_block(pcur); - ut_ad(match->block.page.lock.have_x() - || match->block.page.lock.have_s()); + ut_ad(match->block->page.lock.have_x() + || match->block->page.lock.have_s()); ut_ad(page_is_leaf(cur_block->page.frame)); err = lock_sec_rec_read_check_and_lock( @@ -1293,7 +1293,7 @@ re_scan: ULINT_UNDEFINED, &heap); err = lock_sec_rec_read_check_and_lock( - 0, &match->block, rtr_rec->r_rec, index, + 0, match->block, rtr_rec->r_rec, index, my_offsets, static_cast(mode), type, thr); @@ -1309,7 +1309,7 @@ re_scan: match->locked = true; func_end: - match->block.page.lock.x_unlock(); + match->block->page.lock.x_unlock(); if (heap != NULL) { mem_heap_free(heap); } @@ -3406,7 +3406,7 @@ Row_sel_get_clust_rec_for_mysql::operator()( if (dict_index_is_spatial(sec_index) && btr_cur->rtr_info->matches && (page_align(rec) - == btr_cur->rtr_info->matches->block.page.frame + == btr_cur->rtr_info->matches->block->page.frame || rec != btr_pcur_get_rec(prebuilt->pcur))) { #ifdef UNIV_DEBUG rtr_info_t* rtr_info = btr_cur->rtr_info; diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 9f11b92c26f..f32f4de5173 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -56,84 +56,6 @@ purge_sys_t purge_sys; my_bool srv_purge_view_update_only_debug; #endif /* UNIV_DEBUG */ -/** Sentinel value */ -static const TrxUndoRsegs NullElement; - -/** Default constructor */ -TrxUndoRsegsIterator::TrxUndoRsegsIterator() - : m_rsegs(NullElement), m_iter(m_rsegs.begin()) -{ -} - -/** Sets the next rseg to purge in purge_sys. -Executed in the purge coordinator thread. -@retval false when nothing is to be purged -@retval true when purge_sys.rseg->latch was locked */ -inline bool TrxUndoRsegsIterator::set_next() -{ - ut_ad(!purge_sys.next_stored); - mysql_mutex_lock(&purge_sys.pq_mutex); - - /* Only purge consumes events from the priority queue, user - threads only produce the events. */ - - /* Check if there are more rsegs to process in the - current element. */ - if (m_iter != m_rsegs.end()) { - /* We are still processing rollback segment from - the same transaction and so expected transaction - number shouldn't increase. Undo the increment of - expected commit done by caller assuming rollback - segments from given transaction are done. */ - purge_sys.tail.trx_no = (*m_iter)->last_trx_no(); - } else if (!purge_sys.purge_queue.empty()) { - m_rsegs = purge_sys.purge_queue.top(); - purge_sys.purge_queue.pop(); - ut_ad(purge_sys.purge_queue.empty() - || purge_sys.purge_queue.top() != m_rsegs); - m_iter = m_rsegs.begin(); - } else { - /* Queue is empty, reset iterator. */ - purge_sys.rseg = NULL; - mysql_mutex_unlock(&purge_sys.pq_mutex); - m_rsegs = NullElement; - m_iter = m_rsegs.begin(); - return false; - } - - purge_sys.rseg = *m_iter++; - mysql_mutex_unlock(&purge_sys.pq_mutex); - - /* We assume in purge of externally stored fields that space - id is in the range of UNDO tablespace space ids */ - ut_ad(purge_sys.rseg->space->id == TRX_SYS_SPACE - || srv_is_undo_tablespace(purge_sys.rseg->space->id)); - - purge_sys.rseg->latch.wr_lock(SRW_LOCK_CALL); - trx_id_t last_trx_no = purge_sys.rseg->last_trx_no(); - purge_sys.hdr_offset = purge_sys.rseg->last_offset(); - purge_sys.hdr_page_no = purge_sys.rseg->last_page_no; - - /* Only the purge_coordinator_task will access this object - purge_sys.rseg_iter, or any of purge_sys.hdr_page_no, - purge_sys.tail. - The field purge_sys.head and purge_sys.view are modified by - purge_sys_t::clone_end_view() - in the purge_coordinator_task - while holding exclusive purge_sys.latch. - The purge_sys.view may also be modified by - purge_sys_t::wake_if_not_active() while holding exclusive - purge_sys.latch. - The purge_sys.head may be read by - purge_truncation_callback(). */ - ut_ad(last_trx_no == m_rsegs.trx_no); - ut_a(purge_sys.hdr_page_no != FIL_NULL); - ut_a(purge_sys.tail.trx_no <= last_trx_no); - purge_sys.tail.trx_no = last_trx_no; - - return(true); -} - /** Build a purge 'query' graph. The actual purge is performed by executing this query graph. @return own: the query graph */ @@ -345,7 +267,8 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr) that is known to be corrupted. */ ut_a(flst_add_first(rseg_header, TRX_RSEG + TRX_RSEG_HISTORY, undo_page, uint16_t(page_offset(undo_header) + - TRX_UNDO_HISTORY_NODE), mtr) == DB_SUCCESS); + TRX_UNDO_HISTORY_NODE), rseg->space->free_limit, + mtr) == DB_SUCCESS); mtr->write<2>(*undo_page, TRX_UNDO_SEG_HDR + TRX_UNDO_STATE + undo_page->page.frame, undo_state); @@ -435,6 +358,19 @@ inline dberr_t purge_sys_t::iterator::free_history_rseg(trx_rseg_t &rseg) const mtr_t mtr; bool freed= false; uint32_t rseg_ref= 0; + const auto last_boffset= srv_page_size - TRX_UNDO_LOG_OLD_HDR_SIZE; + /* Technically, rseg.space->free_limit is not protected by + rseg.latch, which we are holding, but rseg.space->latch. The value + that we are reading may become stale (too small) if other pages are + being allocated in this tablespace, for other rollback + segments. Nothing can be added to this rseg without holding + rseg.latch, and hence we can validate the entire file-based list + against the limit that we are reading here. + + Note: The read here may look like a data race. On none of our target + architectures this should be an actual problem, because the uint32_t + value should always fit in a register and be correctly aligned. */ + const auto last_page= rseg.space->free_limit; mtr.start(); @@ -450,13 +386,23 @@ func_exit: } hdr_addr= flst_get_last(TRX_RSEG + TRX_RSEG_HISTORY + rseg_hdr->page.frame); + + if (hdr_addr.page == FIL_NULL) + goto func_exit; + + if (hdr_addr.page >= last_page || + hdr_addr.boffset < TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE || + hdr_addr.boffset >= last_boffset) + { + corrupted: + err= DB_CORRUPTION; + goto func_exit; + } + hdr_addr.boffset= static_cast(hdr_addr.boffset - TRX_UNDO_HISTORY_NODE); loop: - if (hdr_addr.page == FIL_NULL) - goto func_exit; - buf_block_t *b= buf_page_get_gen(page_id_t(rseg.space->id, hdr_addr.page), 0, RW_X_LATCH, nullptr, BUF_GET_POSSIBLY_FREED, @@ -505,11 +451,18 @@ loop: fil_addr_t prev_hdr_addr= flst_get_prev_addr(b->page.frame + hdr_addr.boffset + TRX_UNDO_HISTORY_NODE); + if (prev_hdr_addr.page == FIL_NULL); + else if (prev_hdr_addr.page >= last_page || + prev_hdr_addr.boffset < TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE || + prev_hdr_addr.boffset >= last_boffset) + goto corrupted; + prev_hdr_addr.boffset= static_cast(prev_hdr_addr.boffset - TRX_UNDO_HISTORY_NODE); err= flst_remove(rseg_hdr, TRX_RSEG + TRX_RSEG_HISTORY, b, - uint16_t(hdr_addr.boffset + TRX_UNDO_HISTORY_NODE), &mtr); + uint16_t(hdr_addr.boffset + TRX_UNDO_HISTORY_NODE), + last_page, &mtr); if (UNIV_UNLIKELY(err != DB_SUCCESS)) goto func_exit; @@ -569,45 +522,21 @@ loop: ut_ad(rseg_hdr->page.id() == rseg.page_id()); mtr.memo_push(rseg_hdr, MTR_MEMO_PAGE_X_FIX); + if (hdr_addr.page == FIL_NULL) + goto func_exit; + goto loop; } -/** Cleanse purge queue to remove the rseg that reside in undo-tablespace -marked for truncate. -@param[in] space undo tablespace being truncated */ -static void trx_purge_cleanse_purge_queue(const fil_space_t& space) +void purge_sys_t::cleanse_purge_queue(const fil_space_t &space) { - typedef std::vector purge_elem_list_t; - purge_elem_list_t purge_elem_list; - - mysql_mutex_lock(&purge_sys.pq_mutex); - - /* Remove rseg instances that are in the purge queue before we start - truncate of corresponding UNDO truncate. */ - while (!purge_sys.purge_queue.empty()) { - purge_elem_list.push_back(purge_sys.purge_queue.top()); - purge_sys.purge_queue.pop(); - } - - for (purge_elem_list_t::iterator it = purge_elem_list.begin(); - it != purge_elem_list.end(); - ++it) { - - for (TrxUndoRsegs::iterator it2 = it->begin(); - it2 != it->end(); - ++it2) { - if ((*it2)->space == &space) { - it->erase(it2); - break; - } - } - - if (!it->empty()) { - purge_sys.purge_queue.push(*it); - } - } - - mysql_mutex_unlock(&purge_sys.pq_mutex); + mysql_mutex_lock(&pq_mutex); + auto purge_elem_list= clone_queue_container(); + purge_queue.clear(); + for (auto elem : purge_elem_list) + if (purge_queue::rseg(elem)->space != &space) + purge_queue.push_trx_no_rseg(elem); + mysql_mutex_unlock(&pq_mutex); } dberr_t purge_sys_t::iterator::free_history() const @@ -751,7 +680,7 @@ not_free: const char *file_name= UT_LIST_GET_FIRST(space->chain)->name; sql_print_information("InnoDB: Truncating %s", file_name); - trx_purge_cleanse_purge_queue(*space); + purge_sys.cleanse_purge_queue(*space); /* Lock all modified pages of the tablespace. @@ -870,7 +799,7 @@ buf_block_t *purge_sys_t::get_page(page_id_t id) return nullptr; } -void purge_sys_t::rseg_get_next_history_log() +bool purge_sys_t::rseg_get_next_history_log() { fil_addr_t prev_log_addr; @@ -886,21 +815,24 @@ void purge_sys_t::rseg_get_next_history_log() { const byte *log_hdr= undo_page->page.frame + rseg->last_offset(); prev_log_addr= flst_get_prev_addr(log_hdr + TRX_UNDO_HISTORY_NODE); + if (prev_log_addr.boffset < TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE || + prev_log_addr.boffset >= srv_page_size - TRX_UNDO_LOG_OLD_HDR_SIZE) + goto corrupted; prev_log_addr.boffset = static_cast(prev_log_addr.boffset - TRX_UNDO_HISTORY_NODE); } else - prev_log_addr.page= FIL_NULL; + goto corrupted; - if (prev_log_addr.page == FIL_NULL) + if (prev_log_addr.page >= rseg->space->free_limit) + corrupted: rseg->last_page_no= FIL_NULL; else { /* Read the previous log header. */ trx_id_t trx_no= 0; if (const buf_block_t* undo_page= - get_page(page_id_t(rseg->space->id, - prev_log_addr.page))) + get_page(page_id_t(rseg->space->id, prev_log_addr.page))) { const byte *log_hdr= undo_page->page.frame + prev_log_addr.boffset; trx_no= mach_read_from_8(log_hdr + TRX_UNDO_TRX_NO); @@ -918,12 +850,13 @@ void purge_sys_t::rseg_get_next_history_log() can never produce events from an empty rollback segment. */ mysql_mutex_lock(&pq_mutex); - purge_queue.push(*rseg); + enqueue(*rseg); mysql_mutex_unlock(&pq_mutex); } } rseg->latch.wr_unlock(); + return choose_next_log(); } /** Position the purge sys "iterator" on the undo record to use for purging. @@ -931,11 +864,37 @@ void purge_sys_t::rseg_get_next_history_log() @retval true when purge_sys.rseg->latch was locked */ bool purge_sys_t::choose_next_log() { - if (!rseg_iter.set_next()) - return false; + ut_ad(!next_stored); - hdr_offset= rseg->last_offset(); - hdr_page_no= rseg->last_page_no; + mysql_mutex_lock(&pq_mutex); + if (purge_queue.empty()) { + rseg = nullptr; + mysql_mutex_unlock(&purge_sys.pq_mutex); + return false; + } + rseg= purge_queue.pop(); + mysql_mutex_unlock(&purge_sys.pq_mutex); + + /* We assume in purge of externally stored fields that space + id is in the range of UNDO tablespace space ids */ + ut_ad(rseg->space == fil_system.sys_space || + srv_is_undo_tablespace(rseg->space->id)); + + rseg->latch.wr_lock(SRW_LOCK_CALL); + trx_id_t last_trx_no = rseg->last_trx_no(); + hdr_offset = rseg->last_offset(); + hdr_page_no = rseg->last_page_no; + + /* Only the purge_coordinator_task will access this any of + purge_sys.hdr_page_no, purge_sys.tail. The field purge_sys.head and + purge_sys.view are modified by clone_end_view() in the + purge_coordinator_task while holding exclusive purge_sys.latch. The + purge_sys.view may also be modified by wake_if_not_active() while holding + exclusive purge_sys.latch. The purge_sys.head may be read by + purge_truncation_callback(). */ + ut_a(hdr_page_no != FIL_NULL); + ut_a(tail.trx_no <= last_trx_no); + tail.trx_no = last_trx_no; if (!rseg->needs_purge) { @@ -966,7 +925,7 @@ bool purge_sys_t::choose_next_log() if (!b) goto purge_nothing; undo_rec= - trx_undo_page_get_first_rec(b, page_no, hdr_offset); + trx_undo_page_get_first_rec(b, hdr_page_no, hdr_offset); if (!undo_rec) goto purge_nothing; } @@ -994,12 +953,9 @@ inline trx_purge_rec_t purge_sys_t::get_next_rec(roll_ptr_t roll_ptr) if (!offset) { - /* It is the dummy undo log record, which means that there is no - need to purge this undo log */ - rseg_get_next_history_log(); - - /* Look for the next undo log and record to purge */ - if (choose_next_log()) + /* It is the dummy undo log record, which means that there is no need to + purge this undo log. Look for the next undo log and record to purge */ + if (rseg_get_next_history_log()) rseg->latch.wr_unlock(); return {nullptr, 1}; } @@ -1047,9 +1003,8 @@ inline trx_purge_rec_t purge_sys_t::get_next_rec(roll_ptr_t roll_ptr) else { got_no_rec: - rseg_get_next_history_log(); /* Look for the next undo log and record to purge */ - locked= choose_next_log(); + locked= rseg_get_next_history_log(); } if (locked) diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc index 271f5ea38ae..964dca94ca3 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -454,7 +454,14 @@ static dberr_t trx_rseg_mem_restore(trx_rseg_t *rseg, mtr_t *mtr) { if (!rseg->space) return DB_TABLESPACE_NOT_FOUND; + + /* Access the tablespace header page to recover rseg->space->free_limit */ + page_id_t page_id{rseg->space->id, 0}; dberr_t err; + if (!buf_page_get_gen(page_id, 0, RW_S_LATCH, nullptr, BUF_GET, mtr, &err)) + return err; + mtr->release_last_page(); + page_id.set_page_no(rseg->page_no); const buf_block_t *rseg_hdr= buf_page_get_gen(rseg->page_id(), 0, RW_S_LATCH, nullptr, BUF_GET, mtr, &err); @@ -531,6 +538,11 @@ static dberr_t trx_rseg_mem_restore(trx_rseg_t *rseg, mtr_t *mtr) fil_addr_t node_addr= flst_get_last(TRX_RSEG + TRX_RSEG_HISTORY + rseg_hdr->page.frame); + if (node_addr.page >= rseg->space->free_limit || + node_addr.boffset < TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE || + node_addr.boffset >= srv_page_size - TRX_UNDO_LOG_OLD_HDR_SIZE) + return DB_CORRUPTION; + node_addr.boffset= static_cast(node_addr.boffset - TRX_UNDO_HISTORY_NODE); rseg->last_page_no= node_addr.page; @@ -557,7 +569,7 @@ static dberr_t trx_rseg_mem_restore(trx_rseg_t *rseg, mtr_t *mtr) if (rseg->last_page_no != FIL_NULL) /* There is no need to cover this operation by the purge mutex because we are still bootstrapping. */ - purge_sys.purge_queue.push(*rseg); + purge_sys.enqueue(*rseg); } trx_sys.set_undo_non_empty(rseg->history_size > 0); @@ -598,7 +610,17 @@ dberr_t trx_rseg_array_init() #endif mtr_t mtr; dberr_t err = DB_SUCCESS; - + /* mariabackup --prepare only deals with the redo log and the data + files, not with transactions or the data dictionary, that's why + trx_lists_init_at_db_start() does not invoke purge_sys.create() and + purge queue mutex stays uninitialized, and trx_rseg_mem_restore() quits + before initializing undo log lists. */ + if (srv_operation != SRV_OPERATION_RESTORE) + /* Acquiring purge queue mutex here should be fine from the + deadlock prevention point of view, because executing that + function is a prerequisite for starting the purge subsystem or + any transactions. */ + purge_sys.queue_lock(); for (ulint rseg_id = 0; rseg_id < TRX_SYS_N_RSEGS; rseg_id++) { mtr.start(); if (const buf_block_t* sys = trx_sysf_get(&mtr, false)) { @@ -668,7 +690,8 @@ dberr_t trx_rseg_array_init() mtr.commit(); } - + if (srv_operation != SRV_OPERATION_RESTORE) + purge_sys.queue_unlock(); if (err != DB_SUCCESS) { for (auto& rseg : trx_sys.rseg_array) { while (auto u = UT_LIST_GET_FIRST(rseg.undo_list)) { diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 62cac470b97..1d22b853743 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -1142,15 +1142,23 @@ inline void trx_t::write_serialisation_history(mtr_t *mtr) } else if (rseg->last_page_no == FIL_NULL) { - mysql_mutex_lock(&purge_sys.pq_mutex); + /* trx_sys.assign_new_trx_no() and + purge_sys.enqueue() must be invoked in the same + critical section protected with purge queue mutex to avoid rseg with + greater last commit number to be pushed to purge queue prior to rseg with + lesser last commit number. In other words pushing to purge queue must be + serialized along with assigning trx_no. Otherwise purge coordinator + thread can also fetch redo log records from rseg with greater last commit + number before rseg with lesser one. */ + purge_sys.queue_lock(); trx_sys.assign_new_trx_no(this); const trx_id_t end{rw_trx_hash_element->no}; + rseg->last_page_no= undo->hdr_page_no; /* end cannot be less than anything in rseg. User threads only produce events when a rollback segment is empty. */ - purge_sys.purge_queue.push(TrxUndoRsegs{end, *rseg}); - mysql_mutex_unlock(&purge_sys.pq_mutex); - rseg->last_page_no= undo->hdr_page_no; rseg->set_last_commit(undo->hdr_offset, end); + purge_sys.enqueue(end, *rseg); + purge_sys.queue_unlock(); } else trx_sys.assign_new_trx_no(this); diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc index ccc68dfeef7..c0f5b1fb22c 100644 --- a/storage/innobase/trx/trx0undo.cc +++ b/storage/innobase/trx/trx0undo.cc @@ -134,8 +134,9 @@ trx_undo_page_get_first_rec(const buf_block_t *block, uint32_t page_no, uint16_t offset) { uint16_t start= trx_undo_page_get_start(block, page_no, offset); - return start == trx_undo_page_get_end(block, page_no, offset) - ? nullptr : block->page.frame + start; + uint16_t end= trx_undo_page_get_end(block, page_no, offset); + ut_ad(start <= end); + return start >= end ? nullptr : block->page.frame + start; } /** Get the last undo log record on a page. @@ -149,8 +150,10 @@ trx_undo_rec_t* trx_undo_page_get_last_rec(const buf_block_t *block, uint32_t page_no, uint16_t offset) { + uint16_t start= trx_undo_page_get_start(block, page_no, offset); uint16_t end= trx_undo_page_get_end(block, page_no, offset); - return trx_undo_page_get_start(block, page_no, offset) == end + ut_ad(start <= end); + return start >= end ? nullptr : block->page.frame + mach_read_from_2(block->page.frame + end - 2); } @@ -510,7 +513,7 @@ trx_undo_seg_create(fil_space_t *space, buf_block_t *rseg_hdr, ulint *id, *err = flst_add_last(block, TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST, block, TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE, - mtr); + space->free_limit, mtr); *id = slot_no; mtr->write<4>(*rseg_hdr, TRX_RSEG + TRX_RSEG_UNDO_SLOTS @@ -693,7 +696,8 @@ buf_block_t *trx_undo_add_page(trx_undo_t *undo, mtr_t *mtr, dberr_t *err) mtr->undo_create(*new_block); trx_undo_page_init(*new_block); *err= flst_add_last(header_block, TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST, - new_block, TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE, mtr); + new_block, TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE, + rseg->space->free_limit, mtr); if (UNIV_UNLIKELY(*err != DB_SUCCESS)) new_block= nullptr; else @@ -744,9 +748,11 @@ trx_undo_free_page( buf_page_make_young_if_needed(&header_block->page); + const uint32_t limit = rseg->space->free_limit; + *err = flst_remove(header_block, TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST, undo_block, TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE, - mtr); + limit, mtr); if (UNIV_UNLIKELY(*err != DB_SUCCESS)) { return FIL_NULL; @@ -755,7 +761,13 @@ trx_undo_free_page( const fil_addr_t last_addr = flst_get_last( TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + header_block->page.frame); - if (UNIV_UNLIKELY(last_addr.page == page_no)) { + if (UNIV_UNLIKELY(last_addr.page == page_no) + || UNIV_UNLIKELY(last_addr.page != FIL_NULL + && last_addr.page >= limit) + || UNIV_UNLIKELY(last_addr.boffset < TRX_UNDO_PAGE_HDR + + TRX_UNDO_PAGE_NODE) + || UNIV_UNLIKELY(last_addr.boffset >= srv_page_size + - TRX_UNDO_LOG_OLD_HDR_SIZE)) { *err = DB_CORRUPTION; return FIL_NULL; } @@ -972,8 +984,8 @@ trx_undo_mem_create_at_db_start(trx_rseg_t *rseg, ulint id, uint32_t page_no) ut_ad(id < TRX_RSEG_N_SLOTS); mtr.start(); - const buf_block_t* block = buf_page_get( - page_id_t(rseg->space->id, page_no), 0, RW_X_LATCH, &mtr); + const page_id_t page_id{rseg->space->id, page_no}; + const buf_block_t* block = buf_page_get(page_id, 0, RW_X_LATCH, &mtr); if (UNIV_UNLIKELY(!block)) { corrupted: mtr.commit(); @@ -1075,6 +1087,15 @@ corrupted_type: fil_addr_t last_addr = flst_get_last( TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + block->page.frame); + if (last_addr.page >= rseg->space->free_limit + || last_addr.boffset < TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE + || last_addr.boffset >= srv_page_size + - TRX_UNDO_LOG_OLD_HDR_SIZE) { + corrupted_undo: + ut_free(undo); + goto corrupted; + } + undo->last_page_no = last_addr.page; undo->top_page_no = last_addr.page; @@ -1083,8 +1104,7 @@ corrupted_type: RW_X_LATCH, &mtr); if (UNIV_UNLIKELY(!last)) { - ut_free(undo); - goto corrupted; + goto corrupted_undo; } if (const trx_undo_rec_t* rec = trx_undo_page_get_last_rec( diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 044be038607..ac3ede3865c 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -3390,7 +3390,7 @@ static int sort_one_index(HA_CHECK *param, MARIA_HA *info, length= page.size; bzero(buff+length,keyinfo->block_length-length); if (write_page(share, new_file, buff, keyinfo->block_length, - new_page_pos, MYF(MY_NABP | MY_WAIT_IF_FULL))) + new_page_pos, MYF(MY_NABP | MY_WAIT_IF_FULL) & param->myf_rw)) { _ma_check_print_error(param,"Can't write indexblock, error: %d",my_errno); goto err; diff --git a/storage/maria/ma_extra.c b/storage/maria/ma_extra.c index 49b731af5fc..9116edbd671 100644 --- a/storage/maria/ma_extra.c +++ b/storage/maria/ma_extra.c @@ -601,6 +601,20 @@ uint _ma_file_callback_to_id(void *callback_data) return share ? share->id : 0; } +/* + Disable MY_WAIT_IF_FULL flag for temporary tables + + Temporary tables does not have MY_WAIT_IF_FULL in share->write_flags +*/ + +uint _ma_write_flags_callback(void *callback_data, myf flags) +{ + MARIA_SHARE *share= (MARIA_SHARE*) callback_data; + if (share) + flags&= ~(~share->write_flag & MY_WAIT_IF_FULL); + return flags; +} + /** @brief flushes the data and/or index file of a table diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 8e311ee715c..9bb17576105 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -171,7 +171,6 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, mysql_mutex_lock(&share->intern_lock); info.read_record= share->read_record; share->reopen++; - share->write_flag=MYF(MY_NABP | MY_WAIT_IF_FULL); if (share->options & HA_OPTION_READ_ONLY_DATA) { info.lock_type=F_RDLCK; @@ -986,6 +985,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags, share->options|= HA_OPTION_READ_ONLY_DATA; share->is_log_table= FALSE; + share->write_flag=MYF(MY_NABP | MY_WAIT_IF_FULL); if (open_flags & HA_OPEN_TMP_TABLE || share->options & HA_OPTION_TMP_TABLE) { share->options|= HA_OPTION_TMP_TABLE; diff --git a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c index 144b10a86da..49981e7964a 100644 --- a/storage/maria/ma_pagecache.c +++ b/storage/maria/ma_pagecache.c @@ -687,6 +687,8 @@ static my_bool pagecache_fwrite(PAGECACHE *pagecache, /* FIXME: ENGINE=Aria occasionally writes uninitialized data */ __msan_unpoison(args.page, pagecache->block_size); #endif + /* Reset MY_WAIT_IF_FULL for temporary tables */ + flags= _ma_write_flags_callback(filedesc->callback_data, flags); res= (int)my_pwrite(filedesc->file, args.page, pagecache->block_size, ((my_off_t) pageno << pagecache->shift), flags); (*filedesc->post_write_hook)(res, &args); diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index f3303884200..b12f21e39f9 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -1745,6 +1745,7 @@ extern my_bool ma_yield_and_check_if_killed(MARIA_HA *info, int inx); extern my_bool ma_killed_standalone(MARIA_HA *); extern uint _ma_file_callback_to_id(void *callback_data); +extern uint _ma_write_flags_callback(void *callback_data, myf flags); extern void free_maria_share(MARIA_SHARE *share); static inline void unmap_file(MARIA_HA *info __attribute__((unused))) diff --git a/storage/perfschema/pfs_buffer_container.h b/storage/perfschema/pfs_buffer_container.h index d5745e76249..b5506fe0195 100644 --- a/storage/perfschema/pfs_buffer_container.h +++ b/storage/perfschema/pfs_buffer_container.h @@ -1084,8 +1084,7 @@ template class PFS_buffer_processor { public: - virtual ~PFS_buffer_processor () - {} + virtual ~PFS_buffer_processor()= default; virtual void operator()(T *element) = 0; }; diff --git a/storage/perfschema/pfs_instr_class.cc b/storage/perfschema/pfs_instr_class.cc index 2b1a80d3e11..fa85d8610bf 100644 --- a/storage/perfschema/pfs_instr_class.cc +++ b/storage/perfschema/pfs_instr_class.cc @@ -55,7 +55,7 @@ Indicate if the performance schema is enabled. This flag is set at startup, and never changes. */ -my_bool pfs_enabled= TRUE; +my_bool pfs_enabled= FALSE; /** PFS_INSTRUMENT option settings array diff --git a/storage/perfschema/unittest/pfs_instr_class-t.cc b/storage/perfschema/unittest/pfs_instr_class-t.cc index 7651898d684..76e3668d378 100644 --- a/storage/perfschema/unittest/pfs_instr_class-t.cc +++ b/storage/perfschema/unittest/pfs_instr_class-t.cc @@ -743,6 +743,7 @@ void do_all_tests() int main(int argc, char **argv) { plan(209); + pfs_enabled= 1; MY_INIT(argv[0]); do_all_tests(); my_end(0); diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index 8c24b2691a7..47b257b21cd 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -347,12 +347,23 @@ int ha_spider::open( result_list.last = NULL; result_list.current = NULL; result_list.record_num = 0; - if ( - !(result_list.sqls = new spider_string[share->link_count]) || - !(result_list.insert_sqls = new spider_string[share->link_count]) || - !(result_list.update_sqls = new spider_string[share->link_count]) || - !(result_list.tmp_sqls = new spider_string[share->link_count]) - ) { + if (!(result_list.sqls = new spider_string[share->link_count])) + { + error_num = HA_ERR_OUT_OF_MEM; + goto error_init_result_list; + } + if (!(result_list.insert_sqls = new spider_string[share->link_count])) + { + error_num = HA_ERR_OUT_OF_MEM; + goto error_init_result_list; + } + if (!(result_list.update_sqls = new spider_string[share->link_count])) + { + error_num = HA_ERR_OUT_OF_MEM; + goto error_init_result_list; + } + if (!(result_list.tmp_sqls = new spider_string[share->link_count])) + { error_num = HA_ERR_OUT_OF_MEM; goto error_init_result_list; } diff --git a/storage/spider/ha_spider.h b/storage/spider/ha_spider.h index 4dffdf78553..d22e842342b 100644 --- a/storage/spider/ha_spider.h +++ b/storage/spider/ha_spider.h @@ -792,3 +792,26 @@ public: int lock_tables(); int dml_init(); }; + + +/* This is a hack for ASAN + * Libraries such as libxml2 and libodbc do not like being unloaded before + * exit and will show as a leak in ASAN with no stack trace (as the plugin + * has been unloaded from memory). + * + * The below is designed to trick the compiler into adding a "UNIQUE" symbol + * which can be seen using: + * readelf -s storage/spider/ha_spider.so | grep UNIQUE + * + * Having this symbol means that the plugin remains in memory after dlclose() + * has been called. Thereby letting the libraries clean up properly. + */ +#if defined(__SANITIZE_ADDRESS__) +__attribute__((__used__)) +inline int dummy(void) +{ + static int d; + d++; + return d; +} +#endif diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_19866.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_19866.result index 4386b4cbd4d..dbf0f54c804 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_19866.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_19866.result @@ -72,7 +72,6 @@ SELECT argument FROM mysql.general_log WHERE command_type != 'Execute' AND argum argument select `pkey`,`val` from `auto_test_remote`.`tbl_a` select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 1 -select 1 from (select 1) t0 select `pkey`,`val` from `auto_test_remote`.`tbl_a` select `pkey`,`val` from `auto_test_remote`.`tbl_a` SELECT argument FROM mysql.general_log WHERE command_type != 'Execute' AND argument LIKE '%select %' @@ -86,7 +85,6 @@ argument select `pkey`,`val` from `auto_test_remote2`.`tbl_a` select `pkey`,`val` from `auto_test_remote2`.`tbl_a` select `pkey`,`val` from `auto_test_remote2`.`tbl_a` where `pkey` = 2 -select 1 from (select 1) t0 select `pkey`,`val` from `auto_test_remote2`.`tbl_a` SELECT argument FROM mysql.general_log WHERE command_type != 'Execute' AND argument LIKE '%select %' SELECT pkey, val FROM tbl_a ORDER BY pkey; diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_27172.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_27172.result index 531e48b880b..60ef8e2dea4 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_27172.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_27172.result @@ -66,9 +66,6 @@ id greeting connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE 'select `id`,`greeting` from %'; argument -select `id`,`greeting` from `auto_test_remote`.`tbl_a` where `greeting` = 'Aloha!' and ((`greeting` = 'Aloha!')) -select `id`,`greeting` from `auto_test_remote`.`tbl_b` where `greeting` like 'Aloha%' and ((`greeting` = 'Aloha!')) -select `id`,`greeting` from `auto_test_remote`.`tbl_c` where `greeting` like 'Aloha%' and ((`greeting` = 'Aloha!')) connection child2_1; SET @@global.general_log = @general_log_backup; SET @@global.log_output = @log_output_backup; diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_28856.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_28856.result index 7e4fd3cd084..5fd412b69ea 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_28856.result +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_28856.result @@ -5,6 +5,8 @@ for master_1 for child2 for child3 set spider_same_server_link=1; +set @old_spider_same_server_link=@@global.spider_same_server_link; +set global spider_same_server_link=1; CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); # testing monitoring_* @@ -173,6 +175,7 @@ max(d) 93 drop table t1, t2; drop server srv; +set global spider_same_server_link=@old_spider_same_server_link; for master_1 for child2 for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_33584.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_33584.result new file mode 100644 index 00000000000..796c75cc560 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_33584.result @@ -0,0 +1,4 @@ +set @old_sql_mode=@@global.sql_mode; +set global sql_mode='traditional'; +install soname 'ha_spider'; +set global sql_mode=@old_sql_mode; diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_33679.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_33679.result new file mode 100644 index 00000000000..c021bc70e57 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_33679.result @@ -0,0 +1,25 @@ +# +# MDEV-33679 spider returns parsing failure on valid left join select by translating the on expression to () +# +for master_1 +for child2 +for child3 +CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +CREATE TABLE `t1` (`c` INT(10) UNSIGNED NOT NULL, `b` VARCHAR(255) NOT NULL , PRIMARY KEY (`c`) USING BTREE ) ENGINE=MYISAM; +CREATE TABLE `t2` (`a` INT(10) UNSIGNED NOT NULL, `c` INT(10) UNSIGNED NOT NULL ) ENGINE=MYISAM; +SET spider_same_server_link= on; +CREATE TABLE `t1_spider` (`c` INT(10) UNSIGNED NOT NULL, `b` VARCHAR(255) NOT NULL , PRIMARY KEY (`c`) USING BTREE ) COMMENT='wrapper "mysql",srv "srv", table "t1"' ENGINE=SPIDER; +CREATE TABLE `t2_spider` (`a` INT(10) UNSIGNED NOT NULL, `c` INT(10) UNSIGNED NOT NULL +, PRIMARY KEY (`a`) USING BTREE +) COMMENT='wrapper "mysql",srv "srv",table "t2"' ENGINE=SPIDER; +INSERT INTO t1_spider VALUES(1,'oooo'); +INSERT INTO t2_spider VALUES(1,1); +SELECT t2_spider.a,t1_spider.c FRoM t2_spider LEFT join t1_spider ON (t2_spider.c = t1_spider.c) WHERE t2_spider.a = 1; +a c +1 1 +drop table t1, t2, t1_spider, t2_spider; +drop server srv; +for master_1 +for child2 +for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_33731.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_33731.result new file mode 100644 index 00000000000..a63830f194c --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_33731.result @@ -0,0 +1,10 @@ +for master_1 +for child2 +for child3 +CREATE TABLE t (a INT) ENGINE=Spider PARTITION BY LIST (a) PARTITIONS 2 (PARTITION p1 VALUES IN (0,1),PARTITION p2 VALUES IN (2,3)); +DELETE FROM t PARTITION (p2); +ERROR HY000: Unable to connect to foreign data source: localhost +drop table t; +for master_1 +for child2 +for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_28856.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_28856.test index a1642f7a9cd..9ccfc3784ef 100644 --- a/storage/spider/mysql-test/spider/bugfix/t/mdev_28856.test +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28856.test @@ -10,6 +10,9 @@ # This test covers some table params under consideration for inclusion # in the engine-defined options to be implemented in MDEV-28856. set spider_same_server_link=1; +set @old_spider_same_server_link=@@global.spider_same_server_link; +set global spider_same_server_link=1; + evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); @@ -153,6 +156,7 @@ select max(d) from t1; drop table t1, t2; drop server srv; +set global spider_same_server_link=@old_spider_same_server_link; --disable_query_log --disable_result_log diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_33584.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_33584.test new file mode 100644 index 00000000000..886449716eb --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_33584.test @@ -0,0 +1,11 @@ +# This test tests spider init with global no_zero_date sql mode +set @old_sql_mode=@@global.sql_mode; +set global sql_mode='traditional'; +install soname 'ha_spider'; +set global sql_mode=@old_sql_mode; + +--disable_query_log +--disable_result_log +--source ../../include/clean_up_spider.inc +--enable_result_log +--enable_query_log diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_33679.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_33679.test new file mode 100644 index 00000000000..eee47a21163 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_33679.test @@ -0,0 +1,29 @@ +--echo # +--echo # MDEV-33679 spider returns parsing failure on valid left join select by translating the on expression to () +--echo # +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log +evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); + +CREATE TABLE `t1` (`c` INT(10) UNSIGNED NOT NULL, `b` VARCHAR(255) NOT NULL , PRIMARY KEY (`c`) USING BTREE ) ENGINE=MYISAM; +CREATE TABLE `t2` (`a` INT(10) UNSIGNED NOT NULL, `c` INT(10) UNSIGNED NOT NULL ) ENGINE=MYISAM; +SET spider_same_server_link= on; +CREATE TABLE `t1_spider` (`c` INT(10) UNSIGNED NOT NULL, `b` VARCHAR(255) NOT NULL , PRIMARY KEY (`c`) USING BTREE ) COMMENT='wrapper "mysql",srv "srv", table "t1"' ENGINE=SPIDER; +CREATE TABLE `t2_spider` (`a` INT(10) UNSIGNED NOT NULL, `c` INT(10) UNSIGNED NOT NULL +, PRIMARY KEY (`a`) USING BTREE +) COMMENT='wrapper "mysql",srv "srv",table "t2"' ENGINE=SPIDER; +INSERT INTO t1_spider VALUES(1,'oooo'); +INSERT INTO t2_spider VALUES(1,1); +SELECT t2_spider.a,t1_spider.c FRoM t2_spider LEFT join t1_spider ON (t2_spider.c = t1_spider.c) WHERE t2_spider.a = 1; + +drop table t1, t2, t1_spider, t2_spider; +drop server srv; +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_33731.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_33731.test new file mode 100644 index 00000000000..b98c9620414 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_33731.test @@ -0,0 +1,16 @@ +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log + +CREATE TABLE t (a INT) ENGINE=Spider PARTITION BY LIST (a) PARTITIONS 2 (PARTITION p1 VALUES IN (0,1),PARTITION p2 VALUES IN (2,3)); +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +DELETE FROM t PARTITION (p2); +drop table t; + +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log diff --git a/storage/spider/mysql-test/spider/feature/r/pushdown_case.result b/storage/spider/mysql-test/spider/feature/r/pushdown_case.result new file mode 100644 index 00000000000..613ce377865 --- /dev/null +++ b/storage/spider/mysql-test/spider/feature/r/pushdown_case.result @@ -0,0 +1,57 @@ +# +# MDEV-28993 Spider: Push down CASE statement +# +for master_1 +for child2 +for child3 +set spider_same_server_link= 1; +CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +create table t2 (c int); +create table t1 (c int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +insert into t1 values (42), (3), (848), (100); +explain select case c when 3 then "three" when 42 then "answer" else "other" end from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Storage engine handles GROUP BY +select case c when 3 then "three" when 42 then "answer" else "other" end from t1; +case c when 3 then "three" when 42 then "answer" else "other" end +answer +three +other +other +explain select case c when 3 then "three" when 42 then "answer" end from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Storage engine handles GROUP BY +select case c when 3 then "three" when 42 then "answer" end from t1; +case c when 3 then "three" when 42 then "answer" end +answer +three +NULL +NULL +explain select case when c = 3 then "three" when c = 42 then "answer" else "other" end from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Storage engine handles GROUP BY +select case when c = 3 then "three" when c = 42 then "answer" else "other" end from t1; +case when c = 3 then "three" when c = 42 then "answer" else "other" end +answer +three +other +other +explain select case when c = 3 then "three" when c = 42 then "answer" end from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Storage engine handles GROUP BY +select case when c = 3 then "three" when c = 42 then "answer" end from t1; +case when c = 3 then "three" when c = 42 then "answer" end +answer +three +NULL +NULL +drop table t1, t2; +drop server srv; +for master_1 +for child2 +for child3 +# +# end of test pushdown_case +# diff --git a/storage/spider/mysql-test/spider/feature/r/pushdown_timestamp_diff.result b/storage/spider/mysql-test/spider/feature/r/pushdown_timestamp_diff.result new file mode 100644 index 00000000000..3acd89127c0 --- /dev/null +++ b/storage/spider/mysql-test/spider/feature/r/pushdown_timestamp_diff.result @@ -0,0 +1,111 @@ +# +# MDEV-28992 Spider: Push down TIMESTAMPDIFF function +# +for master_1 +for child2 +for child3 +set spider_same_server_link= 1; +CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +create table t2 ( +a INT, +b CHAR(1), +c DATETIME, +PRIMARY KEY(a) +); +CREATE TABLE t1 ( +a INT, +b CHAR(1), +c DATETIME, +PRIMARY KEY(a) +) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +INSERT INTO t1 (a, b, c) VALUES +(1, 'a', '2018-11-01 10:21:39'), +(2, 'b', '2015-06-30 23:59:59'), +(3, 'c', '2013-11-01 01:01:01'); +interval year +explain select a, b, timestampdiff(year, '2000-01-01 00:00:00', c) from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Storage engine handles GROUP BY +select a, b, timestampdiff(year, '2000-01-01 00:00:00', c) from t1; +a b timestampdiff(year, '2000-01-01 00:00:00', c) +1 a 18 +2 b 15 +3 c 13 +interval quarter +explain select a, b, timestampdiff(quarter, '2000-01-01 00:00:00', c) from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Storage engine handles GROUP BY +select a, b, timestampdiff(quarter, '2000-01-01 00:00:00', c) from t1; +a b timestampdiff(quarter, '2000-01-01 00:00:00', c) +1 a 75 +2 b 61 +3 c 55 +interval month +explain select a, b, timestampdiff(month, '2000-01-01 00:00:00', c) from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Storage engine handles GROUP BY +select a, b, timestampdiff(month, '2000-01-01 00:00:00', c) from t1; +a b timestampdiff(month, '2000-01-01 00:00:00', c) +1 a 226 +2 b 185 +3 c 166 +interval week +explain select a, b, timestampdiff(week, '2000-01-01 00:00:00', c) from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Storage engine handles GROUP BY +select a, b, timestampdiff(week, '2000-01-01 00:00:00', c) from t1; +a b timestampdiff(week, '2000-01-01 00:00:00', c) +1 a 982 +2 b 808 +3 c 721 +interval day +explain select a, b, timestampdiff(day, '2000-01-01 00:00:00', c) from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Storage engine handles GROUP BY +select a, b, timestampdiff(day, '2000-01-01 00:00:00', c) from t1; +a b timestampdiff(day, '2000-01-01 00:00:00', c) +1 a 6879 +2 b 5659 +3 c 5053 +internal hour +explain select a, b, timestampdiff(hour, '2000-01-01 00:00:00', c) from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Storage engine handles GROUP BY +select a, b, timestampdiff(hour, '2000-01-01 00:00:00', c) from t1; +a b timestampdiff(hour, '2000-01-01 00:00:00', c) +1 a 165106 +2 b 135839 +3 c 121273 +internal minute +explain select a, b, timestampdiff(minute, '2000-01-01 00:00:00', c) from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Storage engine handles GROUP BY +select a, b, timestampdiff(minute, '2000-01-01 00:00:00', c) from t1; +a b timestampdiff(minute, '2000-01-01 00:00:00', c) +1 a 9906381 +2 b 8150399 +3 c 7276381 +internal second +explain select a, b, timestampdiff(second, '2000-01-01 00:00:00', c) from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Storage engine handles GROUP BY +select a, b, timestampdiff(second, '2000-01-01 00:00:00', c) from t1; +a b timestampdiff(second, '2000-01-01 00:00:00', c) +1 a 594382899 +2 b 489023999 +3 c 436582861 +internal microsecond +explain select a, b, timestampdiff(microsecond, '2000-01-01 00:00:00', c) from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Storage engine handles GROUP BY +select a, b, timestampdiff(microsecond, '2000-01-01 00:00:00', c) from t1; +a b timestampdiff(microsecond, '2000-01-01 00:00:00', c) +1 a 594382899000000 +2 b 489023999000000 +3 c 436582861000000 +drop table t1, t2; +drop server srv; +for master_1 +for child2 +for child3 diff --git a/storage/spider/mysql-test/spider/feature/t/pushdown_case.test b/storage/spider/mysql-test/spider/feature/t/pushdown_case.test new file mode 100644 index 00000000000..b86edceb615 --- /dev/null +++ b/storage/spider/mysql-test/spider/feature/t/pushdown_case.test @@ -0,0 +1,50 @@ +--echo # +--echo # MDEV-28993 Spider: Push down CASE statement +--echo # +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log +set spider_same_server_link= 1; +evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +create table t2 (c int); +create table t1 (c int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +insert into t1 values (42), (3), (848), (100); + +# everything +let $query= +select case c when 3 then "three" when 42 then "answer" else "other" end from t1; +eval explain $query; +eval $query; + +# no else +let $query= +select case c when 3 then "three" when 42 then "answer" end from t1; +eval explain $query; +eval $query; + +# no value +let $query= +select case when c = 3 then "three" when c = 42 then "answer" else "other" end from t1; +eval explain $query; +eval $query; + +# neither +let $query= +select case when c = 3 then "three" when c = 42 then "answer" end from t1; +eval explain $query; +eval $query; + +drop table t1, t2; +drop server srv; +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log +--echo # +--echo # end of test pushdown_case +--echo # diff --git a/storage/spider/mysql-test/spider/feature/t/pushdown_timestamp_diff.test b/storage/spider/mysql-test/spider/feature/t/pushdown_timestamp_diff.test new file mode 100644 index 00000000000..81251860f74 --- /dev/null +++ b/storage/spider/mysql-test/spider/feature/t/pushdown_timestamp_diff.test @@ -0,0 +1,93 @@ +--echo # +--echo # MDEV-28992 Spider: Push down TIMESTAMPDIFF function +--echo # +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log + +set spider_same_server_link= 1; +evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); + +create table t2 ( + a INT, + b CHAR(1), + c DATETIME, + PRIMARY KEY(a) +); +CREATE TABLE t1 ( + a INT, + b CHAR(1), + c DATETIME, + PRIMARY KEY(a) +) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; + +INSERT INTO t1 (a, b, c) VALUES + (1, 'a', '2018-11-01 10:21:39'), + (2, 'b', '2015-06-30 23:59:59'), + (3, 'c', '2013-11-01 01:01:01'); + +--echo interval year +let $query= +select a, b, timestampdiff(year, '2000-01-01 00:00:00', c) from t1; +eval explain $query; +eval $query; + +--echo interval quarter +let $query= +select a, b, timestampdiff(quarter, '2000-01-01 00:00:00', c) from t1; +eval explain $query; +eval $query; + +--echo interval month +let $query= +select a, b, timestampdiff(month, '2000-01-01 00:00:00', c) from t1; +eval explain $query; +eval $query; + +--echo interval week +let $query= +select a, b, timestampdiff(week, '2000-01-01 00:00:00', c) from t1; +eval explain $query; +eval $query; + +--echo interval day +let $query= +select a, b, timestampdiff(day, '2000-01-01 00:00:00', c) from t1; +eval explain $query; +eval $query; + +--echo internal hour +let $query= +select a, b, timestampdiff(hour, '2000-01-01 00:00:00', c) from t1; +eval explain $query; +eval $query; + +--echo internal minute +let $query= +select a, b, timestampdiff(minute, '2000-01-01 00:00:00', c) from t1; +eval explain $query; +eval $query; + +--echo internal second +let $query= +select a, b, timestampdiff(second, '2000-01-01 00:00:00', c) from t1; +eval explain $query; +eval $query; + +--echo internal microsecond +let $query= +select a, b, timestampdiff(microsecond, '2000-01-01 00:00:00', c) from t1; +eval explain $query; +eval $query; + +drop table t1, t2; +drop server srv; + +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log diff --git a/storage/spider/mysql-test/spider/include/clean_up_spider.inc b/storage/spider/mysql-test/spider/include/clean_up_spider.inc index 1c977bfb66f..249606ec774 100644 --- a/storage/spider/mysql-test/spider/include/clean_up_spider.inc +++ b/storage/spider/mysql-test/spider/include/clean_up_spider.inc @@ -3,7 +3,6 @@ DROP FUNCTION spider_copy_tables; DROP FUNCTION spider_ping_table; DROP FUNCTION spider_bg_direct_sql; DROP FUNCTION spider_direct_sql; ---replace_regex /\.dll/.so/ UNINSTALL SONAME IF EXISTS 'ha_spider'; DROP TABLE IF EXISTS mysql.spider_xa; DROP TABLE IF EXISTS mysql.spider_xa_member; diff --git a/storage/spider/mysql-test/spider/r/partition_join_pushdown_for_single_partition.result b/storage/spider/mysql-test/spider/r/partition_join_pushdown_for_single_partition.result index 850546fa1e9..3eed8df28bf 100644 --- a/storage/spider/mysql-test/spider/r/partition_join_pushdown_for_single_partition.result +++ b/storage/spider/mysql-test/spider/r/partition_join_pushdown_for_single_partition.result @@ -86,10 +86,8 @@ SELECT argument FROM mysql.general_log WHERE command_type != 'Execute' AND argum argument select `value` from `auto_test_remote2`.`tbl_a` where `value` = 5 select `value2` from `auto_test_remote2`.`tbl_b` where `value2` = 5 -select sum('5') `sum(a.value)`,count('5') `count(b.value2)` from (select 1) t0 join (select 1) t1 select `value` from `auto_test_remote2`.`tbl_a` where `value` = 5 select `value2` from `auto_test_remote2`.`tbl_b` where `value2` = 5 -select sum('5') `sum(a.value)`,count('5') `count(b.value2)` from (select 1) t0 join (select 1) t1 SELECT argument FROM mysql.general_log WHERE command_type != 'Execute' AND argument LIKE '%select %' SELECT value FROM tbl_a ORDER BY value; value diff --git a/storage/spider/spd_conn.cc b/storage/spider/spd_conn.cc index 927758960f2..68c5362d0b8 100644 --- a/storage/spider/spd_conn.cc +++ b/storage/spider/spd_conn.cc @@ -56,7 +56,7 @@ extern struct charset_info_st *spd_charset_utf8mb3_bin; extern LEX_CSTRING spider_unique_id; pthread_mutex_t spider_conn_id_mutex; pthread_mutex_t spider_ipport_conn_mutex; -ulonglong spider_conn_id = 1; +ulonglong spider_conn_id; extern pthread_attr_t spider_pt_attr; @@ -93,7 +93,7 @@ extern sql_mode_t pushdown_sql_mode; HASH spider_open_connections; uint spider_open_connections_id; HASH spider_ipport_conns; -long spider_conn_mutex_id = 0; +long spider_conn_mutex_id; const char *spider_open_connections_func_name; const char *spider_open_connections_file_name; diff --git a/storage/spider/spd_copy_tables.cc b/storage/spider/spd_copy_tables.cc index 70ca17f84dd..498f4051e0d 100644 --- a/storage/spider/spd_copy_tables.cc +++ b/storage/spider/spd_copy_tables.cc @@ -298,7 +298,7 @@ int spider_udf_get_copy_tgt_tables( if ( (error_num = spider_get_sys_tables_connect_info( - table_tables, tmp_share, 0, mem_root)) || + table_tables, tmp_share, mem_root)) || (error_num = spider_get_sys_tables_link_status( table_tables, tmp_share, 0, mem_root)) || (error_num = spider_get_sys_tables_link_idx( @@ -968,7 +968,12 @@ long long spider_copy_tables_body( all_link_cnt = copy_tables->link_idx_count[0] + copy_tables->link_idx_count[1]; if ( - !(tmp_sql = new spider_string[all_link_cnt]) || + !(tmp_sql = new spider_string[all_link_cnt]) + ) { + my_error(ER_OUT_OF_RESOURCES, MYF(0), HA_ERR_OUT_OF_MEM); + goto error; + } + if ( !(spider = new ha_spider[all_link_cnt]) ) { my_error(ER_OUT_OF_RESOURCES, MYF(0), HA_ERR_OUT_OF_MEM); @@ -997,13 +1002,6 @@ long long spider_copy_tables_body( tmp_spider->share = table_conn->share; tmp_spider->wide_handler = wide_handler; wide_handler->trx = copy_tables->trx; -/* - if (spider_db_append_set_names(table_conn->share)) - { - my_error(ER_OUT_OF_RESOURCES, MYF(0), HA_ERR_OUT_OF_MEM); - goto error_append_set_names; - } -*/ tmp_spider->conns = &table_conn->conn; tmp_sql[roop_count].init_calc_mem(SPD_MID_COPY_TABLES_BODY_3); tmp_sql[roop_count].set_charset(copy_tables->access_charset); @@ -1043,13 +1041,6 @@ long long spider_copy_tables_body( tmp_spider->share = table_conn->share; tmp_spider->wide_handler = wide_handler; wide_handler->trx = copy_tables->trx; -/* - if (spider_db_append_set_names(table_conn->share)) - { - my_error(ER_OUT_OF_RESOURCES, MYF(0), HA_ERR_OUT_OF_MEM); - goto error_append_set_names; - } -*/ tmp_spider->conns = &table_conn->conn; tmp_sql[roop_count].init_calc_mem(SPD_MID_COPY_TABLES_BODY_5); tmp_sql[roop_count].set_charset(copy_tables->access_charset); @@ -1076,14 +1067,6 @@ long long spider_copy_tables_body( bulk_insert_rows))) goto error_db_udf_copy_tables; -/* - for (table_conn = copy_tables->table_conn[0]; - table_conn; table_conn = table_conn->next) - spider_db_free_set_names(table_conn->share); - for (table_conn = copy_tables->table_conn[1]; - table_conn; table_conn = table_conn->next) - spider_db_free_set_names(table_conn->share); -*/ if (table_list->table) { (thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd)); @@ -1104,8 +1087,7 @@ long long spider_copy_tables_body( } delete [] spider; } - if (tmp_sql) - delete [] tmp_sql; + delete [] tmp_sql; spider_udf_free_copy_tables_alloc(copy_tables); DBUG_RETURN(1); @@ -1113,17 +1095,6 @@ long long spider_copy_tables_body( error_db_udf_copy_tables: error_create_dbton_handler: error_init_dbton_handler: -/* -error_append_set_names: -*/ -/* - for (table_conn = copy_tables->table_conn[0]; - table_conn; table_conn = table_conn->next) - spider_db_free_set_names(table_conn->share); - for (table_conn = copy_tables->table_conn[1]; - table_conn; table_conn = table_conn->next) - spider_db_free_set_names(table_conn->share); -*/ error: if (spider) { diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc index c7e30719e56..5e5787c09a7 100644 --- a/storage/spider/spd_db_conn.cc +++ b/storage/spider/spd_db_conn.cc @@ -63,7 +63,7 @@ pthread_mutex_t spider_open_conn_mutex; const char spider_dig_upper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; /* UTC time zone for timestamp columns */ -Time_zone *UTC = 0; +Time_zone *UTC; int spider_db_connect( const SPIDER_SHARE *share, diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h index 74ed817d0f5..4e9d6b1ae43 100644 --- a/storage/spider/spd_db_include.h +++ b/storage/spider/spd_db_include.h @@ -79,7 +79,6 @@ typedef st_spider_result SPIDER_RESULT; #define SPIDER_SQL_HS_LTEQUAL_STR "<=" #define SPIDER_SQL_HS_LTEQUAL_LEN (sizeof(SPIDER_SQL_HS_LTEQUAL_STR) - 1) -#ifdef ITEM_FUNC_CASE_PARAMS_ARE_PUBLIC #define SPIDER_SQL_CASE_STR "case " #define SPIDER_SQL_CASE_LEN (sizeof(SPIDER_SQL_CASE_STR) - 1) #define SPIDER_SQL_WHEN_STR " when " @@ -90,7 +89,6 @@ typedef st_spider_result SPIDER_RESULT; #define SPIDER_SQL_ELSE_LEN (sizeof(SPIDER_SQL_ELSE_STR) - 1) #define SPIDER_SQL_END_STR " end" #define SPIDER_SQL_END_LEN (sizeof(SPIDER_SQL_END_STR) - 1) -#endif #define SPIDER_SQL_USING_STR " using " #define SPIDER_SQL_USING_LEN (sizeof(SPIDER_SQL_USING_STR) - 1) diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index a6ea9685d85..450e1a0234b 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -1191,7 +1191,7 @@ int spider_db_mbase_result::fetch_table_cardinality( uint num_fields = this->num_fields(); if (num_fields < 12 || num_fields > 14) { - DBUG_PRINT("info",("spider num_fields < 12 || num_fields > 13")); + DBUG_PRINT("info",("spider num_fields < 12 || num_fields > 14")); DBUG_RETURN(ER_SPIDER_INVALID_REMOTE_TABLE_INFO_NUM); } @@ -5399,14 +5399,6 @@ int spider_db_mbase_util::open_item_func( alias_length, use_fields, fields)); } -static bool item_func_is_timestampdiff( - const char *func_name, - int func_name_length -) { - return func_name_length == 13 && - !strncasecmp("timestampdiff", func_name, func_name_length); -} - static bool not_func_should_be_skipped( Item_func *item_func ){ @@ -5476,16 +5468,10 @@ int spider_db_mbase_util::check_item_func( Item_func::Functype func_type = item_func->functype(); DBUG_PRINT("info",("spider functype = %d", func_type)); - const char *func_name = (char*) item_func->func_name(); - int func_name_length = strlen(func_name); - DBUG_PRINT("info",("spider func_name = %s", func_name)); - /* The blacklist of the functions that cannot be pushed down */ switch (func_type) { case Item_func::TRIG_COND_FUNC: - case Item_func::CASE_SEARCHED_FUNC: - case Item_func::CASE_SIMPLE_FUNC: DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); case Item_func::NOT_FUNC: /* Why the following check is necessary? */ @@ -5494,13 +5480,6 @@ int spider_db_mbase_util::check_item_func( break; case Item_func::FUNC_SP: case Item_func::UDF_FUNC: - /* Notes on merging regarding MDEV-29447: please refer to the - following commits for build error or merge conflicts: - 10.6: 1ed20b993b0dd4e95450cab2e8347e5bf4617a69 - 10.9: dd316b6e20265cfd832bb5585cb4c96e716387c8 - 10.10-11: 3f67f110ba1b23a89c5ede0fbeeb203cf5e164f4 - 11.0-1: 17ba6748afa8834df5658361088e6c8e65aca16f - Please remove this comment after merging. */ use_pushdown_udf= spider_param_use_pushdown_udf( spider->wide_handler->trx->thd, spider->share->use_pushdown_udf); if (!use_pushdown_udf) @@ -5510,12 +5489,18 @@ int spider_db_mbase_util::check_item_func( if (spider_db_check_ft_idx(item_func, spider) == MAX_KEY) DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); break; -#ifndef ITEM_FUNC_TIMESTAMPDIFF_ARE_PUBLIC - case Item_func::UNKNOWN_FUNC: - if (item_func_is_timestampdiff(func_name, func_name_length)) - DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); - break; -#endif + case Item_func::MULT_EQUAL_FUNC: + /* If there is still Item_equal by the time of + JOIN::make_aggr_tables_info() where the spider group by handler + is created, it indicates a bug in the optimizer, because there + shouldn't be any. */ + push_warning_printf( + spider->wide_handler->trx->thd, SPIDER_WARN_LEVEL_WARN, + ER_INTERNAL_ERROR, + ER_THD(spider->wide_handler->trx->thd, ER_INTERNAL_ERROR), + "Spider group by handler: Encountered multiple equalities, likely " + "an optimizer bug"); + DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); default: break; } @@ -5557,7 +5542,7 @@ int spider_db_mbase_util::print_item_func( Item *item, **item_list = item_func->arguments(); Field *field; spider_string tmp_str; - uint roop_count, item_count = item_func->argument_count(), start_item = 0; + uint i, item_count = item_func->argument_count(), start_item = 0; LEX_CSTRING org_func_name= {SPIDER_SQL_NULL_CHAR_STR, SPIDER_SQL_NULL_CHAR_LEN}; const char *func_name = SPIDER_SQL_NULL_CHAR_STR, @@ -5566,8 +5551,8 @@ int spider_db_mbase_util::print_item_func( int func_name_length = SPIDER_SQL_NULL_CHAR_LEN, separator_str_length = SPIDER_SQL_NULL_CHAR_LEN, last_str_length = SPIDER_SQL_NULL_CHAR_LEN; - int use_pushdown_udf; - bool merge_func = FALSE; + int use_pushdown_udf, case_when_start, case_when_count; + bool merge_func = FALSE, case_with_else; DBUG_ENTER("spider_db_mbase_util::print_item_func"); DBUG_ASSERT(!check_item_func(item_func, spider, alias, alias_length, use_fields, fields)); @@ -5885,12 +5870,11 @@ int spider_db_mbase_util::print_item_func( alias, alias_length, dbton_id, use_fields, fields)); } else if (!strncasecmp("timestampdiff", func_name, func_name_length)) { -#ifdef ITEM_FUNC_TIMESTAMPDIFF_ARE_PUBLIC Item_func_timestamp_diff *item_func_timestamp_diff = (Item_func_timestamp_diff *) item_func; const char *interval_str; uint interval_len; - switch (item_func_timestamp_diff->int_type) + switch (item_func_timestamp_diff->get_int_type()) { case INTERVAL_YEAR: interval_str = SPIDER_SQL_YEAR_STR; @@ -5941,7 +5925,7 @@ int spider_db_mbase_util::print_item_func( str->q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN); str->q_append(interval_str, interval_len); str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); - + if ((error_num = spider_db_print_item_type(item_list[0], NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); @@ -5962,9 +5946,6 @@ int spider_db_mbase_util::print_item_func( SPIDER_SQL_CLOSE_PAREN_LEN); } DBUG_RETURN(0); -#else - DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); -#endif } } else if (func_name_length == 14) { @@ -6458,7 +6439,83 @@ int spider_db_mbase_util::print_item_func( DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); case Item_func::CASE_SEARCHED_FUNC: case Item_func::CASE_SIMPLE_FUNC: - DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); + /* + Arrangement of arguments: + - Item_func_case_searched: + when1 when2 ... whenk then1 then2 .. thenk [else] + - Item_func_case_simple: + value when1 when2 ... whenk then1 then2 .. thenk [else] + */ + if (item_func->functype() == Item_func::CASE_SEARCHED_FUNC) + { + case_when_start= 0; + case_when_count= item_count / 2; + case_with_else= item_count % 2; + } + else + { + case_when_start= 1; + case_when_count= (item_count - 1) / 2; + case_with_else= item_count % 2 == 0; + } + if (str) + { + if (str->reserve(SPIDER_SQL_CASE_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(SPIDER_SQL_CASE_STR, SPIDER_SQL_CASE_LEN); + } + if (case_when_start > 0) + { + if ((error_num = spider_db_print_item_type( + item_list[0], NULL, spider, str, + alias, alias_length, dbton_id, use_fields, fields))) + DBUG_RETURN(error_num); + } + for (i = 0; i < (uint) case_when_count; i++) + { + if (str) + { + if (str->reserve(SPIDER_SQL_WHEN_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(SPIDER_SQL_WHEN_STR, SPIDER_SQL_WHEN_LEN); + } + if ((error_num = spider_db_print_item_type( + item_list[i + case_when_start], NULL, spider, str, + alias, alias_length, dbton_id, use_fields, fields))) + DBUG_RETURN(error_num); + if (str) + { + if (str->reserve(SPIDER_SQL_THEN_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(SPIDER_SQL_THEN_STR, SPIDER_SQL_THEN_LEN); + } + if ((error_num = spider_db_print_item_type( + item_list[i + case_when_start + case_when_count], NULL, spider, str, + alias, alias_length, dbton_id, use_fields, fields))) + DBUG_RETURN(error_num); + } + if (case_with_else) + { + if (str) + { + if (str->reserve(SPIDER_SQL_ELSE_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(SPIDER_SQL_ELSE_STR, SPIDER_SQL_ELSE_LEN); + } + if ((error_num = spider_db_print_item_type( + item_list[item_count - 1], NULL, spider, str, + alias, alias_length, dbton_id, use_fields, fields))) + DBUG_RETURN(error_num); + } + if (str) + { + if (str->reserve(SPIDER_SQL_END_LEN + SPIDER_SQL_CLOSE_PAREN_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(SPIDER_SQL_END_STR, SPIDER_SQL_END_LEN); + str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, + SPIDER_SQL_CLOSE_PAREN_LEN); + } + DBUG_RETURN(0); case Item_func::JSON_EXTRACT_FUNC: func_name = (char*) item_func->func_name(); func_name_length = strlen(func_name); @@ -6473,6 +6530,18 @@ int spider_db_mbase_util::print_item_func( last_str = SPIDER_SQL_CLOSE_PAREN_STR; last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN; break; + case Item_func::MULT_EQUAL_FUNC: + /* If there is still Item_equal by the time of + JOIN::make_aggr_tables_info() where the spider group by handler + is created, it indicates a bug in the optimizer, because there + shouldn't be any. */ + push_warning_printf( + spider->wide_handler->trx->thd, + SPIDER_WARN_LEVEL_WARN, ER_INTERNAL_ERROR, + ER_THD(spider->wide_handler->trx->thd, ER_INTERNAL_ERROR), + "Spider group by handler: Encountered multiple equalities, likely " + "an optimizer bug"); + DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); default: THD *thd = spider->wide_handler->trx->thd; SPIDER_SHARE *share = spider->share; @@ -6502,13 +6571,13 @@ int spider_db_mbase_util::print_item_func( Loop through the items of the current function expression to print its portion of the statement */ - for (roop_count = start_item; roop_count < item_count; roop_count++) + for (i = start_item; i < item_count; i++) { - item = item_list[roop_count]; + item = item_list[i]; if ((error_num = spider_db_print_item_type(item, field, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); - if (roop_count == 1) + if (i == 1) { /* Remaining operands need to be preceded by the separator */ func_name = separator_str; @@ -6522,7 +6591,7 @@ int spider_db_mbase_util::print_item_func( } /* Print the last operand value */ - item = item_list[roop_count]; + item = item_list[i]; if ((error_num = spider_db_print_item_type(item, field, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); @@ -7155,11 +7224,9 @@ int spider_mbase_share::init() DBUG_RETURN(HA_ERR_OUT_OF_MEM); } - if (keys > 0 && - !(key_hint = new spider_string[keys]) - ) { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } + if (keys > 0) + if (!(key_hint = new spider_string[keys])) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); for (roop_count = 0; roop_count < keys; roop_count++) { key_hint[roop_count].init_calc_mem(SPD_MID_MBASE_SHARE_INIT_2); @@ -7167,12 +7234,12 @@ int spider_mbase_share::init() } DBUG_PRINT("info",("spider key_hint=%p", key_hint)); - if ( - !(table_select = new spider_string[1]) || - (keys > 0 && - !(key_select = new spider_string[keys]) - ) || - (error_num = create_table_names_str()) || + if (!(table_select = new spider_string[1])) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + if (keys > 0) + if (!(key_select = new spider_string[keys])) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + if ((error_num = create_table_names_str()) || (table_share && ( (error_num = create_column_name_str()) || @@ -7323,11 +7390,18 @@ int spider_mbase_share::create_table_names_str() table_names_str = NULL; db_names_str = NULL; db_table_str = NULL; - if ( - !(table_names_str = new spider_string[spider_share->all_link_count]) || - !(db_names_str = new spider_string[spider_share->all_link_count]) || - !(db_table_str = new spider_string[spider_share->all_link_count]) - ) { + if (!(table_names_str = new spider_string[spider_share->all_link_count])) + { + error_num = HA_ERR_OUT_OF_MEM; + goto error; + } + if (!(db_names_str = new spider_string[spider_share->all_link_count])) + { + error_num = HA_ERR_OUT_OF_MEM; + goto error; + } + if (!(db_table_str = new spider_string[spider_share->all_link_count])) + { error_num = HA_ERR_OUT_OF_MEM; goto error; } @@ -7476,11 +7550,9 @@ int spider_mbase_share::create_column_name_str() Field **field; TABLE_SHARE *table_share = spider_share->table_share; DBUG_ENTER("spider_mbase_share::create_column_name_str"); - if ( - table_share->fields && - !(column_name_str = new spider_string[table_share->fields]) - ) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); + if (table_share->fields) + if (!(column_name_str = new spider_string[table_share->fields])) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); for (field = table_share->field, str = column_name_str; *field; field++, str++) { diff --git a/storage/spider/spd_include.h b/storage/spider/spd_include.h index 755bd711af2..3828f19b891 100644 --- a/storage/spider/spd_include.h +++ b/storage/spider/spd_include.h @@ -1416,6 +1416,7 @@ typedef struct st_spider_table_mon st_spider_table_mon *next; } SPIDER_TABLE_MON; +/* List of `SPIDER_TABLE_MON's */ typedef struct st_spider_table_mon_list { char *key; diff --git a/storage/spider/spd_init_query.h b/storage/spider/spd_init_query.h index 0e42e228481..c2e33d97a4b 100644 --- a/storage/spider/spd_init_query.h +++ b/storage/spider/spd_init_query.h @@ -20,8 +20,10 @@ */ static LEX_STRING spider_init_queries[] = { + /* Use the default SQL_MODE for this connection. */ {C_STRING_WITH_LEN( - "SET @@SQL_MODE = REGEXP_REPLACE(@@SQL_MODE, '(ORACLE|NO_ZERO_DATE)', '');" + "SET @@SQL_MODE = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO," + "NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';" )}, {C_STRING_WITH_LEN( "SET @@OLD_MODE = CONCAT(@@OLD_MODE, ',UTF8_IS_UTF8MB3');" diff --git a/storage/spider/spd_ping_table.cc b/storage/spider/spd_ping_table.cc index 722b4ccab3c..80b40c6211e 100644 --- a/storage/spider/spd_ping_table.cc +++ b/storage/spider/spd_ping_table.cc @@ -50,6 +50,8 @@ extern PSI_mutex_key spd_key_mutex_mon_list_update_status; extern PSI_mutex_key spd_key_mutex_mon_table_cache; #endif +/* Array (of size `spider_udf_table_mon_mutex_count') of hashes of +`SPIDER_TABLE_MON_LIST'. */ HASH *spider_udf_table_mon_list_hash; uint spider_udf_table_mon_list_hash_id; const char *spider_udf_table_mon_list_hash_func_name; @@ -59,23 +61,43 @@ pthread_mutex_t *spider_udf_table_mon_mutexes; pthread_cond_t *spider_udf_table_mon_conds; pthread_mutex_t spider_mon_table_cache_mutex; +/* A cache to store distinct SPIDER_MON_KEYs with db name, table name +and link id read from mysql.spider_link_mon_servers table. Initialised +and populated in spider_init_ping_table_mon_cache(), and used in +spider_ping_table_cache_compare(). The udf +spider_flush_table_mon_cache is used to flag a initialisation. */ DYNAMIC_ARRAY spider_mon_table_cache; uint spider_mon_table_cache_id; const char *spider_mon_table_cache_func_name; const char *spider_mon_table_cache_file_name; ulong spider_mon_table_cache_line_no; -volatile ulonglong spider_mon_table_cache_version = 0; -volatile ulonglong spider_mon_table_cache_version_req = 1; +/* The mon table cache version, initialised at 0, and always no +greater than spider_mon_table_cache_version_req. When the inequality +is strict, an initialisation of spider_mon_table_cache will be +triggered. */ +volatile ulonglong spider_mon_table_cache_version; +/* The required mon table cache version, incremented by one by the +udf spider_flush_table_mon_cache */ +volatile ulonglong spider_mon_table_cache_version_req; + /* Get or create a `SPIDER_TABLE_MON_LIST' for a key `str' */ SPIDER_TABLE_MON_LIST *spider_get_ping_table_mon_list( SPIDER_TRX *trx, THD *thd, - spider_string *str, + spider_string *str, /* The key to search in + `spider_udf_table_mon_list_hash', + usually in the format of + "./$db_name/$table_name000000000$link_idx" */ uint conv_name_length, int link_idx, char *static_link_id, uint static_link_id_length, - uint32 server_id, + uint32 server_id, /* The server id of the monitor + server, used for creating a new + table mon list having a + `SPIDER_TABLE_MON' corresponding to + the server id as the `current' + field */ bool need_lock, int *error_num ) { @@ -85,6 +107,7 @@ SPIDER_TABLE_MON_LIST *spider_get_ping_table_mon_list( ulonglong mon_table_cache_version; my_hash_value_type hash_value; DBUG_ENTER("spider_get_ping_table_mon_list"); + /* Reset the cache if the version does not match the requirement */ if (spider_mon_table_cache_version != spider_mon_table_cache_version_req) { SPD_INIT_ALLOC_ROOT(&mem_root, 4096, 0, MYF(MY_WME)); @@ -97,6 +120,9 @@ SPIDER_TABLE_MON_LIST *spider_get_ping_table_mon_list( free_root(&mem_root, MYF(0)); } + /* Search for the table mon list in the hash, if one is not found or + if it is found but has the wrong cache version, create and + initialise a new one. */ mutex_hash= spider_udf_calc_hash(str->c_ptr(), spider_udf_table_mon_mutex_count); DBUG_PRINT("info",("spider hash key=%s", str->c_ptr())); @@ -113,12 +139,15 @@ SPIDER_TABLE_MON_LIST *spider_get_ping_table_mon_list( table_mon_list->mon_table_cache_version != mon_table_cache_version ) { + /* If table_mon_list is found but the cache version does not + match, remove it from the hash and free it. */ if ( table_mon_list && table_mon_list->mon_table_cache_version != mon_table_cache_version ) spider_release_ping_table_mon_list_loop(mutex_hash, table_mon_list); - + /* create and initialise `table_mon_list' and insert it into the + hash */ if (!(table_mon_list = spider_get_ping_table_tgt(thd, str->c_ptr(), conv_name_length, link_idx, static_link_id, static_link_id_length, server_id, str, need_lock, error_num))) @@ -240,6 +269,14 @@ int spider_release_ping_table_mon_list( DBUG_RETURN(0); } +/* + Look for a `SPIDER_MON_KEY` in `spider_mon_table_cache' whose db and + table name and link_idx matching `name' and `link_idx' with wild + card matching. If a match is found, create `SPIDER_TABLE_MON's from + all rows in mysql.spider_link_mon_servers that match the info in the + `SPIDER_MON_KEY' and populate the `table_mon_list' with these + `SPIDER_TABLE_MON's. +*/ int spider_get_ping_table_mon( THD *thd, SPIDER_TABLE_MON_LIST *table_mon_list, @@ -316,6 +353,8 @@ int spider_get_ping_table_mon( goto error; create_table_mon: + /* Find the first row in mysql.spider_link_mon_servers matching the + db name, table name and link_idx */ if ((error_num = spider_get_sys_table_by_idx(table_link_mon, table_key, table_link_mon->s->primary_key, 3))) { @@ -323,6 +362,9 @@ create_table_mon: goto error; } + /* create one `SPIDER_TABLE_MON' per row in + mysql.spider_link_mon_servers with matching db name, table name and + link_idx, and add it to `table_mon_list'. */ do { if (!(table_mon = (SPIDER_TABLE_MON *) spider_bulk_malloc(spider_current_trx, SPD_MID_GET_PING_TABLE_MON_1, MYF(MY_WME | MY_ZEROFILL), @@ -356,7 +398,7 @@ create_table_mon: (error_num = spider_get_sys_link_mon_server_id( table_link_mon, &table_mon->server_id, mem_root)) || (error_num = spider_get_sys_link_mon_connect_info( - table_link_mon, tmp_share, 0, mem_root)) + table_link_mon, tmp_share, mem_root)) ) { table_link_mon->file->print_error(error_num, MYF(0)); spider_sys_index_end(table_link_mon); @@ -418,15 +460,21 @@ error: DBUG_RETURN(error_num); } +/* + creates and return table_mon_list associated with table with `name' + and `link_idx'th link. +*/ SPIDER_TABLE_MON_LIST *spider_get_ping_table_tgt( THD *thd, - char *name, + char *name, /* The table name, usually fully qualified */ uint name_length, int link_idx, char *static_link_id, uint static_link_id_length, - uint32 server_id, - spider_string *str, + uint32 server_id, /* The server_id will determine the + `current' field of the returned + `SPIDER_TABLE_MON_LIST'. */ + spider_string *str, /* str->c_ptr() == name */ bool need_lock, int *error_num ) { @@ -471,6 +519,7 @@ SPIDER_TABLE_MON_LIST *spider_get_ping_table_tgt( memcpy(key_str, str->ptr(), table_mon_list->key_length); tmp_share->access_charset = thd->variables.character_set_client; + /* Open mysql.spider_tables */ if ( !(table_tables = spider_open_sys_table( thd, SPIDER_SYS_TABLES_TABLE_NAME_STR, @@ -480,6 +529,8 @@ SPIDER_TABLE_MON_LIST *spider_get_ping_table_tgt( my_error(*error_num, MYF(0)); goto error; } + /* store db and table names and link idx in mysql.spider_tables for + reading */ spider_store_tables_name(table_tables, name, name_length); if (static_link_id) { @@ -503,9 +554,10 @@ SPIDER_TABLE_MON_LIST *spider_get_ping_table_tgt( goto error; } } + /* Populate tmp_share with info read from mysql.spider_tables */ if ( (*error_num = spider_get_sys_tables_connect_info( - table_tables, tmp_share, 0, &mem_root)) || + table_tables, tmp_share, &mem_root)) || (*error_num = spider_get_sys_tables_link_status( table_tables, tmp_share, 0, &mem_root)) ) { @@ -527,9 +579,8 @@ SPIDER_TABLE_MON_LIST *spider_get_ping_table_tgt( tmp_share, name, name_length )) || (*error_num = spider_create_conn_keys(tmp_share)) || -/* - (*error_num = spider_db_create_table_names_str(tmp_share)) || -*/ + /* Pinally, populate `table_mon_list' with newly created + `SPIDER_TABLE_MON's */ (*error_num = spider_get_ping_table_mon( thd, table_mon_list, name, name_length, link_idx, server_id, &mem_root, need_lock)) @@ -819,6 +870,11 @@ error_open_table_tables: DBUG_RETURN(error_num); } +/* + Initialise `spider_mon_table_cache' by scanning the + mysql.spider_link_mon_servers table, creating distinct + `SPIDER_MON_KEY's with the info and inserting them into the cache. +*/ int spider_init_ping_table_mon_cache( THD *thd, MEM_ROOT *mem_root, @@ -847,6 +903,7 @@ int spider_init_ping_table_mon_cache( /* reset */ spider_mon_table_cache.elements = 0; + /* start at the first row */ if ((error_num = spider_sys_index_first(table_link_mon, table_link_mon->s->primary_key))) { @@ -863,10 +920,16 @@ int spider_init_ping_table_mon_cache( mon_key.table_name_length = SPIDER_SYS_LINK_MON_TABLE_TABLE_NAME_SIZE + 1; mon_key.link_id_length = SPIDER_SYS_LINK_MON_TABLE_LINK_ID_SIZE + 1; do { + /* update content of `mon_key' */ if ((error_num = spider_get_sys_link_mon_key(table_link_mon, &mon_key, mem_root, &same))) goto error_get_sys_link_mon_key; + /* `mon_key' has changed content. since + mysql.spider_link_mon_servers is indexed by db_name, + table_name, link_idx, and server_id, it is possible that + different server_ids share the same mon_key which only has + db_name, table_name, link_idx */ if (!same) { mon_key.sort = spider_calc_for_sort(3, mon_key.db_name, @@ -937,6 +1000,13 @@ error_open_sys_table: DBUG_RETURN(error_num); } +/* + Read from msyql.spider_link_mon_servers table fields the db name, + table name and link_id and search for them with wild card matching + in `spider_mon_table_cache'. store the db name, table name, and + link_id of the matching `SPIDER_MON_KEY' back to the table field on + success. +*/ int spider_ping_table_cache_compare( TABLE *table, MEM_ROOT *mem_root @@ -1213,9 +1283,6 @@ long long spider_ping_table_body( DBUG_PRINT("info",("spider mon_table_result->result_status=SPIDER_LINK_MON_NG 2")); if (table_mon_list->mon_status != SPIDER_LINK_MON_NG) { -/* - pthread_mutex_lock(&table_mon_list->update_status_mutex); -*/ pthread_mutex_lock(&spider_udf_table_mon_mutexes[table_mon_list->mutex_hash]); if (table_mon_list->mon_status != SPIDER_LINK_MON_NG) { @@ -1230,9 +1297,6 @@ long long spider_ping_table_body( conv_name.c_ptr(), conv_name_length, link_idx, TRUE); status_changed_to_ng = TRUE; } -/* - pthread_mutex_unlock(&table_mon_list->update_status_mutex); -*/ pthread_mutex_unlock(&spider_udf_table_mon_mutexes[table_mon_list->mutex_hash]); if (status_changed_to_ng) { @@ -1286,9 +1350,6 @@ long long spider_ping_table_body( DBUG_PRINT("info",("spider mon_table_result->result_status=SPIDER_LINK_MON_NG 3")); if (table_mon_list->mon_status != SPIDER_LINK_MON_NG) { -/* - pthread_mutex_lock(&table_mon_list->update_status_mutex); -*/ pthread_mutex_lock(&spider_udf_table_mon_mutexes[table_mon_list->mutex_hash]); if (table_mon_list->mon_status != SPIDER_LINK_MON_NG) { @@ -1303,9 +1364,6 @@ long long spider_ping_table_body( conv_name.c_ptr(), conv_name_length, link_idx, TRUE); status_changed_to_ng = TRUE; } -/* - pthread_mutex_unlock(&table_mon_list->update_status_mutex); -*/ pthread_mutex_unlock(&spider_udf_table_mon_mutexes[table_mon_list->mutex_hash]); if (status_changed_to_ng) { @@ -1349,9 +1407,6 @@ long long spider_ping_table_body( mon_table_result->result_status == SPIDER_LINK_MON_NG && table_mon_list->mon_status != SPIDER_LINK_MON_NG ) { -/* - pthread_mutex_lock(&table_mon_list->update_status_mutex); -*/ pthread_mutex_lock(&spider_udf_table_mon_mutexes[table_mon_list->mutex_hash]); if (table_mon_list->mon_status != SPIDER_LINK_MON_NG) { @@ -1366,9 +1421,6 @@ long long spider_ping_table_body( conv_name.c_ptr(), conv_name_length, link_idx, TRUE); status_changed_to_ng = TRUE; } -/* - pthread_mutex_unlock(&table_mon_list->update_status_mutex); -*/ pthread_mutex_unlock(&spider_udf_table_mon_mutexes[table_mon_list->mutex_hash]); if (status_changed_to_ng) { @@ -1539,9 +1591,9 @@ int spider_ping_table_mon_from_table( SPIDER_SHARE *share, int base_link_idx, uint32 server_id, - char *conv_name, + char *conv_name, /* Usually fully qualified table name */ uint conv_name_length, - int link_idx, + int link_idx, /* The link id to ping */ char *where_clause, uint where_clause_length, long monitoring_kind, @@ -1551,9 +1603,6 @@ int spider_ping_table_mon_from_table( ) { int error_num = 0, current_mon_count, flags; uint32 first_sid; -/* - THD *thd = trx->thd; -*/ SPIDER_TABLE_MON_LIST *table_mon_list; SPIDER_TABLE_MON *table_mon; SPIDER_MON_TABLE_RESULT mon_table_result; @@ -1622,6 +1671,7 @@ int spider_ping_table_mon_from_table( if (monitoring_flag & 1) flags |= SPIDER_UDF_PING_TABLE_USE_ALL_MONITORING_NODES; + /* Get or create `table_mon_list' for `conv_name_str'. */ if (!(table_mon_list = spider_get_ping_table_mon_list(trx, thd, &conv_name_str, conv_name_length, link_idx, share->static_link_ids[link_idx], @@ -1653,6 +1703,8 @@ int spider_ping_table_mon_from_table( table_mon = table_mon_list->current; first_sid = table_mon->server_id; current_mon_count = 1; + /* Call spider_ping_table on each table_mon of `table_mon_list', + until one succeeds */ while (TRUE) { DBUG_PRINT("info",("spider thd->killed=%s", @@ -1697,16 +1749,13 @@ int spider_ping_table_mon_from_table( if (!spider_db_udf_ping_table_mon_next( thd, table_mon, mon_conn, &mon_table_result, conv_name, conv_name_length, link_idx, - where_clause, where_clause_length, -1, table_mon_list->list_size, + where_clause, where_clause_length, /*first_sid=*/-1, table_mon_list->list_size, 0, 0, 0, flags, monitoring_limit)) { if ( mon_table_result.result_status == SPIDER_LINK_MON_NG && table_mon_list->mon_status != SPIDER_LINK_MON_NG ) { -/* - pthread_mutex_lock(&table_mon_list->update_status_mutex); -*/ pthread_mutex_lock(&spider_udf_table_mon_mutexes[table_mon_list->mutex_hash]); if (table_mon_list->mon_status != SPIDER_LINK_MON_NG) { @@ -1721,9 +1770,6 @@ int spider_ping_table_mon_from_table( spider_sys_log_tables_link_failed(thd, conv_name, conv_name_length, link_idx, need_lock); } -/* - pthread_mutex_unlock(&table_mon_list->update_status_mutex); -*/ pthread_mutex_unlock(&spider_udf_table_mon_mutexes[table_mon_list->mutex_hash]); } table_mon_list->last_caller_result = mon_table_result.result_status; diff --git a/storage/spider/spd_sys_table.cc b/storage/spider/spd_sys_table.cc index 912e02a72b0..bd3e7a6f061 100644 --- a/storage/spider/spd_sys_table.cc +++ b/storage/spider/spd_sys_table.cc @@ -574,6 +574,11 @@ int spider_check_sys_table_for_update_all_columns( HA_WHOLE_KEY, HA_READ_KEY_EXACT)); } +/* + Creates a key (`table_key') consisting of `col_count' key parts of + `idx'th index of the table, then positions an index cursor to that + key. +*/ int spider_get_sys_table_by_idx( TABLE *table, char *table_key, @@ -629,7 +634,7 @@ int spider_sys_index_next_same( int spider_sys_index_first( TABLE *table, - const int idx + const int idx /* which index to use */ ) { int error_num; DBUG_ENTER("spider_sys_index_first"); @@ -871,6 +876,10 @@ void spider_store_xa_member_info( DBUG_VOID_RETURN; } +/* + Store db and table names from `name' to `table's corresponding + fields +*/ void spider_store_tables_name( TABLE *table, const char *name, @@ -2149,14 +2158,16 @@ int spider_get_sys_tables( DBUG_RETURN(0); } +/* Read table info from mysql.spider_tables into a `SPIDER_SHARE' */ int spider_get_sys_tables_connect_info( - TABLE *table, - SPIDER_SHARE *share, - int link_idx, + TABLE *table, /* The mysql.spider_tables table */ + SPIDER_SHARE *share, /* The `SPIDER_SHARE' to + update info */ MEM_ROOT *mem_root ) { char *ptr; int error_num = 0; + const int link_idx= 0; DBUG_ENTER("spider_get_sys_tables_connect_info"); DBUG_PRINT("info",("spider link_idx:%d", link_idx)); if ((ptr = get_field(mem_root, table->field[SPIDER_TABLES_PRIORITY_POS]))) @@ -2431,9 +2442,14 @@ int spider_get_sys_tables_monitoring_binlog_pos_at_failing( DBUG_RETURN(error_num); } +/* + Read the link status from mysql.spider_tables into a `SPIDER_SHARE' + with default value 1 (`SPIDER_LINK_STATUS_OK') +*/ int spider_get_sys_tables_link_status( - TABLE *table, - SPIDER_SHARE *share, + TABLE *table, /* The mysql.spider_tables table */ + SPIDER_SHARE *share, /* The share to read link + status into */ int link_idx, MEM_ROOT *mem_root ) { @@ -2607,11 +2623,17 @@ error: DBUG_RETURN(error_num); } +/* Populate `mon_key' from the current row in `table' */ int spider_get_sys_link_mon_key( - TABLE *table, - SPIDER_MON_KEY *mon_key, + TABLE *table, /* the mysql.spider_link_mon_servers + table */ + SPIDER_MON_KEY *mon_key, /* output, to be populated in this + function */ MEM_ROOT *mem_root, - int *same + int *same /* output, true if the data from the + current row in the table agrees with + existing data in `mon_key' and false + otherwise */ ) { char *db_name, *table_name, *link_id; uint db_name_length, table_name_length, link_id_length; @@ -2627,6 +2649,7 @@ int spider_get_sys_link_mon_key( DBUG_RETURN(ER_SPIDER_SYS_TABLE_VERSION_NUM); } + /* get data for `mon_key' from the table record */ if (!(db_name= get_field(mem_root, table->field[SPIDER_LINK_MON_SERVERS_DB_NAME_POS]))) @@ -2678,9 +2701,12 @@ int spider_get_sys_link_mon_key( DBUG_RETURN(0); } +/* Get the server id from the spider_link_mon_servers table field */ int spider_get_sys_link_mon_server_id( - TABLE *table, - uint32 *server_id, + TABLE *table, /* the + mysql.spider_link_mon_servers + table */ + uint32 *server_id, /* output to server_id */ MEM_ROOT *mem_root ) { char *ptr; @@ -2694,14 +2720,17 @@ int spider_get_sys_link_mon_server_id( DBUG_RETURN(error_num); } +/* Get connect info from the spider_link_mon_servers table fields */ int spider_get_sys_link_mon_connect_info( - TABLE *table, - SPIDER_SHARE *share, - int link_idx, + TABLE *table, /* The + mysql.spider_link_mon_servers + table */ + SPIDER_SHARE *share, /* The output spider_share */ MEM_ROOT *mem_root ) { char *ptr; int error_num = 0; + const int link_idx= 0; DBUG_ENTER("spider_get_sys_link_mon_connect_info"); if ( !table->field[SPIDER_LINK_MON_SERVERS_SERVER_POS]->is_null() && @@ -2930,9 +2959,6 @@ int spider_get_link_statuses( if ( (error_num == HA_ERR_KEY_NOT_FOUND || error_num == HA_ERR_END_OF_FILE) ) { -/* - table->file->print_error(error_num, MYF(0)); -*/ DBUG_RETURN(error_num); } } else if ((error_num = diff --git a/storage/spider/spd_sys_table.h b/storage/spider/spd_sys_table.h index f198332363d..ce3897c7382 100644 --- a/storage/spider/spd_sys_table.h +++ b/storage/spider/spd_sys_table.h @@ -56,6 +56,7 @@ #define SPIDER_SYS_LINK_MON_TABLE_TABLE_NAME_SIZE 64 #define SPIDER_SYS_LINK_MON_TABLE_LINK_ID_SIZE 64 +/* For insertion into `spider_mon_table_cache'. */ class SPIDER_MON_KEY: public SPIDER_SORT { public: @@ -401,7 +402,6 @@ int spider_get_sys_tables( int spider_get_sys_tables_connect_info( TABLE *table, SPIDER_SHARE *share, - int link_idx, MEM_ROOT *mem_root ); @@ -478,7 +478,6 @@ int spider_get_sys_link_mon_server_id( int spider_get_sys_link_mon_connect_info( TABLE *table, SPIDER_SHARE *share, - int link_idx, MEM_ROOT *mem_root ); diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index 208b804f5ca..72561aeac11 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -124,6 +124,11 @@ extern SPIDER_DBTON spider_dbton_mysql; extern SPIDER_DBTON spider_dbton_mariadb; SPIDER_THREAD *spider_table_sts_threads; SPIDER_THREAD *spider_table_crd_threads; +extern volatile ulonglong spider_mon_table_cache_version; +extern volatile ulonglong spider_mon_table_cache_version_req; +extern ulonglong spider_conn_id; +extern Time_zone *UTC; +extern ulonglong spider_thread_id; #ifdef HAVE_PSI_INTERFACE PSI_mutex_key spd_key_mutex_tbl; @@ -3468,11 +3473,13 @@ error_alloc_conn_string: DBUG_RETURN(error_num); } +/* Set default connect info of a SPIDER_SHARE if needed */ int spider_set_connect_info_default( - SPIDER_SHARE *share, - partition_element *part_elem, - partition_element *sub_elem, - TABLE_SHARE *table_share + SPIDER_SHARE *share, /* The `SPIDER_SHARE' to set + default connect info */ + partition_element *part_elem, /* partition info used as input */ + partition_element *sub_elem, /* subpartition info used as input */ + TABLE_SHARE *table_share /* table share info used as input */ ) { bool check_socket; bool check_database; @@ -3706,22 +3713,6 @@ int spider_set_connect_info_default( } } -/* - if (!share->static_link_ids[roop_count]) - { - DBUG_PRINT("info",("spider create default static_link_ids")); - share->static_link_ids_lengths[roop_count] = - SPIDER_DB_STATIC_LINK_ID_LEN; - if ( - !(share->static_link_ids[roop_count] = spider_create_string( - SPIDER_DB_STATIC_LINK_ID_STR, - share->static_link_ids_lengths[roop_count])) - ) { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - } -*/ - if (port_has_default_value) { share->tgt_ports[roop_count] = MYSQL_PORT; @@ -3811,7 +3802,11 @@ int spider_set_connect_info_default( DBUG_RETURN(0); } - +/* + This function is a no-op if all share->tgt_dbs and + share->tgt_table_names are non-null, otherwise it may assign them + with db_name and table_name +*/ int spider_set_connect_info_default_db_table( SPIDER_SHARE *share, const char *db_name, @@ -3897,6 +3892,11 @@ int spider_set_connect_info_default_db_table( DBUG_RETURN(0); } +/* + Parse `dbtable_name' into db name and table name, and call + spider_set_connect_info_default_db_table() to set the db/table name + values of `share' if needed +*/ int spider_set_connect_info_default_dbtable( SPIDER_SHARE *share, const char *dbtable_name, @@ -4256,12 +4256,12 @@ SPIDER_SHARE *spider_create_share( share->table.key_info = table_share->key_info; share->table.read_set = &table_share->all_set; - if (table_share->keys > 0 && - !(share->key_hint = new spider_string[table_share->keys]) - ) { - *error_num = HA_ERR_OUT_OF_MEM; - goto error_init_hint_string; - } + if (table_share->keys > 0) + if (!(share->key_hint = new spider_string[table_share->keys])) + { + *error_num = HA_ERR_OUT_OF_MEM; + goto error_init_hint_string; + } for (roop_count = 0; roop_count < (int) table_share->keys; roop_count++) share->key_hint[roop_count].init_calc_mem(SPD_MID_CREATE_SHARE_2); DBUG_PRINT("info",("spider share->key_hint=%p", share->key_hint)); @@ -5797,7 +5797,7 @@ int spider_open_all_tables( (error_num = spider_get_sys_tables( table_tables, &db_name, &table_name, &mem_root)) || (error_num = spider_get_sys_tables_connect_info( - table_tables, &tmp_share, 0, &mem_root)) || + table_tables, &tmp_share, &mem_root)) || (error_num = spider_set_connect_info_default( &tmp_share, NULL, @@ -6084,7 +6084,11 @@ int spider_close_connection( } spider_rollback(spider_hton_ptr, thd, TRUE); + + Dummy_error_handler deh; // suppress network errors at this stage + thd->push_internal_handler(&deh); spider_free_trx(trx, TRUE, false); + thd->pop_internal_handler(); DBUG_RETURN(0); } @@ -6346,6 +6350,12 @@ int spider_db_init( handlerton *spider_hton = (handlerton *)p; DBUG_ENTER("spider_db_init"); + spider_mon_table_cache_version= 0; + spider_mon_table_cache_version_req= 1; + spider_conn_id= 1; + spider_conn_mutex_id= 0; + UTC = 0; + spider_thread_id = 1; const LEX_CSTRING aria_name={STRING_WITH_LEN("Aria")}; if (!plugin_is_ready(&aria_name, MYSQL_STORAGE_ENGINE_PLUGIN)) DBUG_RETURN(HA_ERR_RETRY_INIT); diff --git a/storage/spider/spd_trx.cc b/storage/spider/spd_trx.cc index ebf9a7776cb..b7a92286fa9 100644 --- a/storage/spider/spd_trx.cc +++ b/storage/spider/spd_trx.cc @@ -41,7 +41,7 @@ extern struct charset_info_st *spd_charset_utf8mb3_bin; extern handlerton *spider_hton_ptr; extern SPIDER_DBTON spider_dbton[SPIDER_DBTON_SIZE]; pthread_mutex_t spider_thread_id_mutex; -ulonglong spider_thread_id = 1; +ulonglong spider_thread_id; #ifdef HAVE_PSI_INTERFACE extern PSI_mutex_key spd_key_mutex_udf_table; diff --git a/tpool/tpool_generic.cc b/tpool/tpool_generic.cc index fd97b4464af..f0637044639 100644 --- a/tpool/tpool_generic.cc +++ b/tpool/tpool_generic.cc @@ -628,7 +628,7 @@ void thread_pool_generic::check_idle(std::chrono::system_clock::time_point now) } /* Switch timer off after 1 minute of idle time */ - if (now - idle_since > max_idle_time) + if (now - idle_since > max_idle_time && m_active_threads.empty()) { idle_since= invalid_timestamp; switch_timer(timer_state_t::OFF); @@ -729,6 +729,13 @@ bool thread_pool_generic::add_thread() if (n_threads >= m_max_threads) return false; + + /* + Deadlock danger exists, so monitor pool health + with maintenance timer. + */ + switch_timer(timer_state_t::ON); + if (n_threads >= m_min_threads) { auto now = std::chrono::system_clock::now(); @@ -739,8 +746,6 @@ bool thread_pool_generic::add_thread() Throttle thread creation and wakeup deadlock detection timer, if is it off. */ - switch_timer(timer_state_t::ON); - return false; } } @@ -801,6 +806,7 @@ thread_pool_generic::thread_pool_generic(int min_threads, int max_threads) : m_tasks_dequeued(), m_wakeups(), m_spurious_wakeups(), + m_timer_state(timer_state_t::ON), m_in_shutdown(), m_timestamp(), m_long_tasks_count(), @@ -813,6 +819,7 @@ thread_pool_generic::thread_pool_generic(int min_threads, int max_threads) : m_maintenance_timer(thread_pool_generic::maintenance_func, this, nullptr) { set_concurrency(); + // start the timer m_maintenance_timer.set_time(0, (int)m_timer_interval.count()); } diff --git a/unittest/mysys/my_getopt-t.c b/unittest/mysys/my_getopt-t.c index 6ffbfb20789..a71c4676d63 100644 --- a/unittest/mysys/my_getopt-t.c +++ b/unittest/mysys/my_getopt-t.c @@ -378,10 +378,10 @@ int main(int argc __attribute__((unused)), char **argv) "res:%d, argc:%d, opt_ull:%llu", res, arg_c, opt_ull); run("--ull=-100", NULL); - ok(res==9 && arg_c==1 && opt_ull==0ULL, + ok(res==13 && arg_c==0 && opt_ull==0ULL, "res:%d, argc:%d, opt_ull:%llu", res, arg_c, opt_ull); run("--ul=-100", NULL); - ok(res==9 && arg_c==1 && opt_ul==0UL, + ok(res==13 && arg_c==0 && opt_ul==0UL, "res:%d, argc:%d, opt_ul:%lu", res, arg_c, opt_ul); my_end(0); diff --git a/wsrep-lib b/wsrep-lib index 7d108eb8706..dfc4bdb8a5d 160000 --- a/wsrep-lib +++ b/wsrep-lib @@ -1 +1 @@ -Subproject commit 7d108eb8706962abc74705bedfc60cfc3f296ea6 +Subproject commit dfc4bdb8a5dcbd6fbea007ad3beff899a6b5b7bd