diff options
author | Jan Lindström <jan.lindstrom@mariadb.com> | 2018-08-23 17:14:13 +0300 |
---|---|---|
committer | Jan Lindström <jan.lindstrom@mariadb.com> | 2018-08-23 17:14:13 +0300 |
commit | e4ec889c21ef24fbdfef3d0a36828807241877da (patch) | |
tree | 41eb54838e6b6277cb02d0ec3cf7ec0866d78103 | |
parent | d6d63f4844bf87adb6250d1b1d43e86feab9a5d0 (diff) | |
parent | 420cfe4efe72674d4291c0d5a46205ab70b6b91c (diff) | |
download | mariadb-git-bb-10.4-galera-jantmp.tar.gz |
Merge remote-tracking branch 'wsrep/10.3_wsrep_api-26' into 10.4bb-10.4-galera-jantmp
Conflicts:
mysql-test/include/check-testcase.test
mysql-test/include/wait_until_connected_again.inc
mysql-test/suite/galera/disabled.def
mysql-test/suite/galera/r/MW-416.result
mysql-test/suite/galera/r/galera#500.result
mysql-test/suite/galera/r/galera_var_dirty_reads.result
mysql-test/suite/galera/t/MW-416.test
mysql-test/suite/galera/t/galera#500.test
sql/handler.cc
sql/item_strfunc.cc
sql/item_strfunc.h
sql/slave.cc
sql/sql_class.cc
sql/sql_class.h
sql/sql_connect.cc
sql/sql_insert.cc
sql/sql_parse.cc
sql/sql_plugin.cc
sql/sql_prepare.cc
sql/wsrep_applier.cc
sql/wsrep_mysqld.cc
sql/wsrep_mysqld.h
sql/wsrep_sst.cc
sql/wsrep_thd.cc
storage/innobase/handler/ha_innodb.cc
833 files changed, 36459 insertions, 2490 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 58b6cc62e9f..5477e68a113 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -380,6 +380,11 @@ INCLUDE(mariadb_connector_c) # this does ADD_SUBDIRECTORY(libmariadb) # Add storage engines and plugins. CONFIGURE_PLUGINS() +IF(WITH_WSREP) +ADD_SUBDIRECTORY(wsrep) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/wsrep) +ENDIF() + ADD_SUBDIRECTORY(include) ADD_SUBDIRECTORY(dbug) ADD_SUBDIRECTORY(strings) @@ -401,10 +406,6 @@ IF(NOT WITHOUT_SERVER) ADD_SUBDIRECTORY(unittest/embedded) ENDIF(WITH_EMBEDDED_SERVER) - IF(WITH_WSREP) - ADD_SUBDIRECTORY(wsrep) - ENDIF() - ADD_SUBDIRECTORY(mysql-test) ADD_SUBDIRECTORY(mysql-test/lib/My/SafeProcess) ADD_SUBDIRECTORY(sql-bench) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 9fa127380a4..3d77ef754ae 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -26,7 +26,7 @@ ENDIF() OPTION(WITH_WSREP "WSREP replication API (to use, e.g. Galera Replication library)" ${with_wsrep_default}) # Set the patch version -SET(WSREP_PATCH_VERSION "23") +SET(WSREP_PATCH_VERSION "22") # Obtain wsrep API version FILE(STRINGS "${MySQL_SOURCE_DIR}/wsrep/wsrep_api.h" WSREP_API_VERSION diff --git a/include/mysql/service_wsrep.h b/include/mysql/service_wsrep.h index 1540a5e56fe..d0d00cf2013 100644 --- a/include/mysql/service_wsrep.h +++ b/include/mysql/service_wsrep.h @@ -1,4 +1,5 @@ #ifndef MYSQL_SERVICE_WSREP_INCLUDED + /* Copyright (c) 2015 MariaDB Corporation Ab This program is free software; you can redistribute it and/or modify @@ -48,15 +49,16 @@ enum wsrep_exec_mode { Transaction procession after it has been replicated in prepare stage and has passed certification. */ - LOCAL_COMMIT + LOCAL_COMMIT, + LOCAL_ROLLBACK, }; enum wsrep_query_state { QUERY_IDLE, QUERY_EXEC, QUERY_COMMITTING, + QUERY_ORDERED_COMMIT, QUERY_EXITING, - QUERY_ROLLINGBACK, }; enum wsrep_trx_status { @@ -67,12 +69,12 @@ enum wsrep_trx_status { }; struct xid_t; -struct wsrep; +struct wsrep_st; struct wsrep_ws_handle; struct wsrep_buf; extern struct wsrep_service_st { - struct wsrep * (*get_wsrep_func)(); + struct wsrep_st * (*get_wsrep_func)(); my_bool (*get_wsrep_certify_nonPK_func)(); my_bool (*get_wsrep_debug_func)(); my_bool (*get_wsrep_drupal_282555_workaround_func)(); @@ -80,26 +82,22 @@ extern struct wsrep_service_st { my_bool (*get_wsrep_load_data_splitting_func)(); my_bool (*get_wsrep_log_conflicts_func)(); long (*get_wsrep_protocol_version_func)(); - my_bool (*wsrep_aborting_thd_contains_func)(THD *thd); - void (*wsrep_aborting_thd_enqueue_func)(THD *thd); bool (*wsrep_consistency_check_func)(THD *thd); - int (*wsrep_is_wsrep_xid_func)(const struct xid_t *xid); + int (*wsrep_is_wsrep_xid_func)(const void *xid); long long (*wsrep_xid_seqno_func)(const struct xid_t *xid); const unsigned char* (*wsrep_xid_uuid_func)(const struct xid_t *xid); - void (*wsrep_lock_rollback_func)(); - int (*wsrep_on_func)(MYSQL_THD); - void (*wsrep_post_commit_func)(THD* thd, bool all); - bool (*wsrep_prepare_key_func)(const unsigned char*, size_t, const unsigned char*, size_t, struct wsrep_buf*, size_t*); - enum wsrep_trx_status (*wsrep_run_wsrep_commit_func)(THD *thd, bool all); + int (*wsrep_on_func)(void *); + bool (*wsrep_prepare_key_for_innodb_func)(THD* thd, const unsigned char*, size_t, const unsigned char*, size_t, struct wsrep_buf*, size_t*); void (*wsrep_thd_LOCK_func)(THD *thd); void (*wsrep_thd_UNLOCK_func)(THD *thd); void (*wsrep_thd_awake_func)(THD *thd, my_bool signal); enum wsrep_conflict_state (*wsrep_thd_conflict_state_func)(MYSQL_THD, my_bool); + my_thread_id (*wsrep_thd_thread_id_func)(THD *thd); const char * (*wsrep_thd_conflict_state_str_func)(THD *thd); enum wsrep_exec_mode (*wsrep_thd_exec_mode_func)(THD *thd); const char * (*wsrep_thd_exec_mode_str_func)(THD *thd); enum wsrep_conflict_state (*wsrep_thd_get_conflict_state_func)(MYSQL_THD); - my_bool (*wsrep_thd_is_BF_func)(MYSQL_THD , my_bool); + my_bool (*wsrep_thd_is_BF_func)(void* , my_bool); my_bool (*wsrep_thd_is_wsrep_func)(MYSQL_THD thd); char * (*wsrep_thd_query_func)(THD *thd); enum wsrep_query_state (*wsrep_thd_query_state_func)(THD *thd); @@ -107,14 +105,15 @@ extern struct wsrep_service_st { int (*wsrep_thd_retry_counter_func)(THD *thd); void (*wsrep_thd_set_conflict_state_func)(THD *thd, enum wsrep_conflict_state state); bool (*wsrep_thd_ignore_table_func)(THD *thd); - long long (*wsrep_thd_trx_seqno_func)(THD *thd); + int64_t (*wsrep_thd_trx_seqno_func)(const THD *thd); struct wsrep_ws_handle * (*wsrep_thd_ws_handle_func)(THD *thd); int (*wsrep_trx_is_aborting_func)(MYSQL_THD thd); int (*wsrep_trx_order_before_func)(MYSQL_THD, MYSQL_THD); - void (*wsrep_unlock_rollback_func)(); } *wsrep_service; + #ifdef MYSQL_DYNAMIC_PLUGIN + #define get_wsrep() wsrep_service->get_wsrep_func() #define get_wsrep_certify_nonPK() wsrep_service->get_wsrep_certify_nonPK_func() #define get_wsrep_debug() wsrep_service->get_wsrep_debug_func() @@ -123,17 +122,12 @@ extern struct wsrep_service_st { #define get_wsrep_load_data_splitting() wsrep_service->get_wsrep_load_data_splitting_func() #define get_wsrep_log_conflicts() wsrep_service->get_wsrep_log_conflicts_func() #define get_wsrep_protocol_version() wsrep_service->get_wsrep_protocol_version_func() -#define wsrep_aborting_thd_contains(T) wsrep_service->wsrep_aborting_thd_contains_func(T) -#define wsrep_aborting_thd_enqueue(T) wsrep_service->wsrep_aborting_thd_enqueue_func(T) #define wsrep_consistency_check(T) wsrep_service->wsrep_consistency_check_func(T) #define wsrep_is_wsrep_xid(X) wsrep_service->wsrep_is_wsrep_xid_func(X) #define wsrep_xid_seqno(X) wsrep_service->wsrep_xid_seqno_func(X) #define wsrep_xid_uuid(X) wsrep_service->wsrep_xid_uuid_func(X) -#define wsrep_lock_rollback() wsrep_service->wsrep_lock_rollback_func() #define wsrep_on(X) wsrep_service->wsrep_on_func(X) -#define wsrep_post_commit(T,A) wsrep_service->wsrep_post_commit_func(T,A) -#define wsrep_prepare_key(A,B,C,D,E,F) wsrep_service->wsrep_prepare_key_func(A,B,C,D,E,F) -#define wsrep_run_wsrep_commit(T,A) wsrep_service->wsrep_run_wsrep_commit_func(T,A) +#define wsrep_prepare_key_for_innodb(A,B,C,D,E,F,G) wsrep_service->wsrep_prepare_key_for_innodb_func(A,B,C,D,E,F.G) #define wsrep_thd_LOCK(T) wsrep_service->wsrep_thd_LOCK_func(T) #define wsrep_thd_UNLOCK(T) wsrep_service->wsrep_thd_UNLOCK_func(T) #define wsrep_thd_awake(T,S) wsrep_service->wsrep_thd_awake_func(T,S) @@ -148,13 +142,13 @@ extern struct wsrep_service_st { #define wsrep_thd_query_state(T) wsrep_service->wsrep_thd_query_state_func(T) #define wsrep_thd_query_state_str(T) wsrep_service->wsrep_thd_query_state_str_func(T) #define wsrep_thd_retry_counter(T) wsrep_service->wsrep_thd_retry_counter_func(T) -#define wsrep_thd_set_conflict_state(T,S) wsrep_service->wsrep_thd_set_conflict_state_func(T,S) #define wsrep_thd_ignore_table(T) wsrep_service->wsrep_thd_ignore_table_func(T) #define wsrep_thd_trx_seqno(T) wsrep_service->wsrep_thd_trx_seqno_func(T) #define wsrep_thd_ws_handle(T) wsrep_service->wsrep_thd_ws_handle_func(T) #define wsrep_trx_is_aborting(T) wsrep_service->wsrep_trx_is_aborting_func(T) #define wsrep_trx_order_before(T1,T2) wsrep_service->wsrep_trx_order_before_func(T1,T2) -#define wsrep_unlock_rollback() wsrep_service->wsrep_unlock_rollback_func() +#define wsrep_thd_thread_id(T) wsrep_service->wsrep_thd_thread_id_func(T) +#define wsrep_thd_xid(T,X,S) wsrep_service->wsrep_thd_xid_func(T,X,S) #define wsrep_debug get_wsrep_debug() #define wsrep_log_conflicts get_wsrep_log_conflicts() @@ -173,10 +167,11 @@ extern my_bool wsrep_load_data_splitting; extern my_bool wsrep_drupal_282555_workaround; extern my_bool wsrep_recovery; extern long wsrep_protocol_version; +extern my_thread_id wsrep_thd_thread_id(THD *thd); bool wsrep_consistency_check(THD *thd); -bool wsrep_prepare_key(const unsigned char* cache_key, size_t cache_key_len, const unsigned char* row_id, size_t row_id_len, struct wsrep_buf* key, size_t* key_len); -char *wsrep_thd_query(THD *thd); +bool wsrep_prepare_key_for_innodb(THD* thd, const unsigned char* cache_key, size_t cache_key_len, const unsigned char* row_id, size_t row_id_len, struct wsrep_buf* key, size_t* key_len); +extern "C" char *wsrep_thd_query(THD *thd); const char *wsrep_thd_conflict_state_str(THD *thd); const char *wsrep_thd_exec_mode_str(THD *thd); const char *wsrep_thd_query_state_str(THD *thd); @@ -185,15 +180,15 @@ enum wsrep_conflict_state wsrep_thd_get_conflict_state(MYSQL_THD thd); enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd); enum wsrep_query_state wsrep_thd_query_state(THD *thd); enum wsrep_trx_status wsrep_run_wsrep_commit(THD *thd, bool all); -int wsrep_is_wsrep_xid(const struct xid_t* xid); +int wsrep_is_wsrep_xid(const void* xid); long long wsrep_xid_seqno(const struct xid_t* xid); const unsigned char* wsrep_xid_uuid(const struct xid_t* xid); -int wsrep_on(MYSQL_THD thd); +int wsrep_on(void *); int wsrep_thd_retry_counter(THD *thd); int wsrep_trx_is_aborting(MYSQL_THD thd); int wsrep_trx_order_before(MYSQL_THD thd1, MYSQL_THD thd2); long get_wsrep_protocol_version(); -long long wsrep_thd_trx_seqno(THD *thd); +int64_t wsrep_thd_trx_seqno(const THD *thd); my_bool get_wsrep_certify_nonPK(); my_bool get_wsrep_debug(); my_bool get_wsrep_drupal_282555_workaround(); @@ -201,20 +196,18 @@ my_bool get_wsrep_recovery(); my_bool get_wsrep_load_data_splitting(); my_bool get_wsrep_log_conflicts(); my_bool wsrep_aborting_thd_contains(THD *thd); -my_bool wsrep_thd_is_BF(MYSQL_THD thd, my_bool sync); +my_bool wsrep_thd_is_BF(void* thd, my_bool sync); my_bool wsrep_thd_is_wsrep(MYSQL_THD thd); -struct wsrep *get_wsrep(); +struct wsrep_st *get_wsrep(); struct wsrep_ws_handle *wsrep_thd_ws_handle(THD *thd); void wsrep_aborting_thd_enqueue(THD *thd); -void wsrep_lock_rollback(); void wsrep_post_commit(THD* thd, bool all); void wsrep_thd_LOCK(THD *thd); void wsrep_thd_UNLOCK(THD *thd); void wsrep_thd_awake(THD *thd, my_bool signal); void wsrep_thd_set_conflict_state(THD *thd, enum wsrep_conflict_state state); bool wsrep_thd_ignore_table(THD *thd); -void wsrep_unlock_rollback(); - +void wsrep_thd_xid(const void *thd_ptr, void *xid, size_t xid_size); #endif #ifdef __cplusplus diff --git a/include/wsrep.h b/include/wsrep.h index 0c06bb32b31..def7ad1b377 100644 --- a/include/wsrep.h +++ b/include/wsrep.h @@ -39,6 +39,11 @@ if (WSREP(thd) && !thd->lex->no_write_to_binlog \ && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) goto error; +#define WSREP_SYNC_WAIT(thd_, before_) \ + { if (WSREP_CLIENT(thd_) && \ + wsrep_sync_wait(thd_, before_)) goto error; } + + #define WSREP_DEBUG(...) \ if (wsrep_debug) WSREP_LOG(sql_print_information, ##__VA_ARGS__) #define WSREP_INFO(...) WSREP_LOG(sql_print_information, ##__VA_ARGS__) diff --git a/mysql-test/include/galera_cluster.inc b/mysql-test/include/galera_cluster.inc index c1834c3c26f..7f76ea59c7f 100644 --- a/mysql-test/include/galera_cluster.inc +++ b/mysql-test/include/galera_cluster.inc @@ -8,5 +8,11 @@ --let $galera_cluster_size = 2 --source include/galera_init.inc +--source include/have_innodb.inc +--source include/galera_wait_ready.inc +--connection node_2 +--source include/galera_wait_ready.inc --source include/have_innodb.inc + +--connection node_1 diff --git a/mysql-test/suite/galera/include/galera_have_debug_sync.inc b/mysql-test/include/galera_have_debug_sync.inc index 7c0156052d8..7c0156052d8 100644 --- a/mysql-test/suite/galera/include/galera_have_debug_sync.inc +++ b/mysql-test/include/galera_have_debug_sync.inc diff --git a/mysql-test/include/galera_wait_sync_point.inc b/mysql-test/include/galera_wait_sync_point.inc index cf3a4980186..c0951b220b4 100644 --- a/mysql-test/include/galera_wait_sync_point.inc +++ b/mysql-test/include/galera_wait_sync_point.inc @@ -1,6 +1,17 @@ --let $wait_timeout = 10 --let $wsrep_on_orig = `SELECT @@wsrep_on` SET SESSION wsrep_on = 0; + +# +# following is only for debugging purposes +# should be commented out when test wporks as planned +# +#--sleep 1 +# SHOW PROCESSLIST; +#SHOW STATUS LIKE 'wsrep_%'; +#--echo $galera_sync_point + --let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters' AND VARIABLE_VALUE = '$galera_sync_point' --source include/wait_condition.inc --eval SET SESSION wsrep_on = $wsrep_on_orig + diff --git a/mysql-test/include/have_ipv6.inc b/mysql-test/include/have_ipv6.inc new file mode 100644 index 00000000000..752dd0db53e --- /dev/null +++ b/mysql-test/include/have_ipv6.inc @@ -0,0 +1,20 @@ +# Check if ipv6 is available. +# +--disable_query_log +--disable_result_log +--disable_abort_on_error +connect (checkcon123456789,::1,root,,test); +if($mysql_errno) +{ + skip No IPv6 support; +} +connection default; +if(!$mysql_errno) +{ + disconnect checkcon123456789; +} +--enable_abort_on_error +--enable_result_log +--enable_query_log +# end check + diff --git a/mysql-test/include/kill_galera.inc b/mysql-test/include/kill_galera.inc new file mode 100644 index 00000000000..d7f665df6c7 --- /dev/null +++ b/mysql-test/include/kill_galera.inc @@ -0,0 +1,20 @@ +--echo Killing server ... + +# Write file to make mysql-test-run.pl expect the crash, but don't start it +--let $_server_id= `SELECT @@server_id` +--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.$_server_id.expect +--exec echo "wait" > $_expect_file_name + +# Kill the connected server +--disable_reconnect +--let KILL_NODE_PIDFILE = `SELECT @@pid_file` + +--perl + my $pid_filename = $ENV{'KILL_NODE_PIDFILE'}; + my $mysqld_pid = `cat $pid_filename`; + chomp($mysqld_pid); + system("kill -9 $mysqld_pid"); + exit(0); +EOF + +--source include/wait_until_disconnected.inc diff --git a/mysql-test/include/mtr_warnings.sql b/mysql-test/include/mtr_warnings.sql index b7b2a316dfb..28974cff315 100644 --- a/mysql-test/include/mtr_warnings.sql +++ b/mysql-test/include/mtr_warnings.sql @@ -229,6 +229,52 @@ INSERT INTO global_suppressions VALUES MDEV-12501 -- set --maturity-level by default */ ("Plugin .* is of maturity level .* while the server is .*"), + ("WSREP:*down context*"), + ("WSREP: Failed to send state UUID:*"), + ("WSREP: wsrep_sst_receive_address is set to '127.0.0.1"), + ("WSREP: option --wsrep-causal-reads is deprecated"), + ("WSREP: --wsrep-causal-reads=ON takes precedence over --wsrep-sync-wait=0"), + ("WSREP: Could not open saved state file for reading: "), + ("WSREP: Could not open state file for reading: "), + ("WSREP: access file\\(.*gvwstate\\.dat\\) failed\\(No such file or directory\\)"), + ("WSREP: Gap in state sequence\\. Need state transfer\\."), + ("WSREP: Failed to prepare for incremental state transfer: Local state UUID \\(00000000-0000-0000-0000-000000000000\\) does not match group state UUID"), + ("WSREP: No existing UUID has been found, so we assume that this is the first time that this server has been started\\. Generating a new UUID: "), + ("WSREP: last inactive check more than"), + ("WSREP: binlog cache not empty \\(0 bytes\\) at connection close"), + ("WSREP: SQL statement was ineffective"), + ("WSREP: Refusing exit for the last slave thread"), + ("WSREP: Quorum: No node with complete state"), + ("WSREP: Failed to report last committed"), + ("Slave SQL: Error 'Duplicate entry"), + ("Query apply warning:"), + ("WSREP: Ignoring error"), + ("WSREP: Initial position was provided by configuration or SST, avoiding override"), + ("Warning: Using a password on the command line interface can be insecure"), + ("InnoDB: Error: Table \"mysql\"\\.\"innodb_table_stats\" not found"), + ("but it is impossible to select State Transfer donor: Resource temporarily unavailable"), + ("WSREP: Could not find peer"), + ("WSREP: discarding established \\(time wait\\)"), + ("sending install message failed: Resource temporarily unavailable"), + ("WSREP: Ignoring possible split-brain \\(allowed by configuration\\) from view"), + ("WSREP: no nodes coming from prim view, prim not possible"), + ("WSREP: Failed to prepare for incremental state transfer: Local state seqno is undefined:"), + ("WSREP: gcs_caused\\(\\) returned -107 \\(Transport endpoint is not connected\\)"), + ("WSREP: gcs_caused\\(\\) returned -57 \\(Socket is not connected\\)"), + ("WSREP: gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)"), + ("Action message in non-primary configuration from member"), + ("SYNC message from member"), + ("InnoDB: Resizing redo log from"), + ("InnoDB: Starting to delete and rewrite log files"), + ("InnoDB: New log files created, LSN="), +-- WSREP: Send action {0x7f86280147f0, 73, STATE_REQUEST} returned -107 (Transport endpoint is not connected) + ("Transport endpoint is not connected"), + ("Socket is not connected"), +-- "WSREP: Protocol violation. JOIN message sender 1.0 (host-91-221-67-96) is not in state transfer (SYNCED). Message ignored. + ("is not in state transfer"), + ("JOIN message from member .* in non-primary configuration"), + ("install timer expired"), + ("Last Applied Action message in non-primary configuration from member"), ("THE_LAST_SUPPRESSION")|| diff --git a/mysql-test/include/restart_mysqld.inc b/mysql-test/include/restart_mysqld.inc index 3d3e55db4ac..8cf2798b592 100644 --- a/mysql-test/include/restart_mysqld.inc +++ b/mysql-test/include/restart_mysqld.inc @@ -5,6 +5,5 @@ # --source include/restart_mysqld.inc --source include/not_embedded.inc - --source include/shutdown_mysqld.inc --source include/start_mysqld.inc diff --git a/mysql-test/include/wait_wsrep_ready.inc b/mysql-test/include/wait_wsrep_ready.inc index 2dd1ef7f1ab..7ff65136c92 100644 --- a/mysql-test/include/wait_wsrep_ready.inc +++ b/mysql-test/include/wait_wsrep_ready.inc @@ -6,13 +6,26 @@ --disable_query_log --disable_result_log +# +# if node is not ready, SELECT @@GLOBAL.WSREP_ON below does not +# succeed. However, we can force it to succeed by running the SELECT +# with dirty reads configuration. So we prepare for that +# +--let $my_dirty_reads= `select @@wsrep_dirty_reads` +SET wsrep_dirty_reads = ON; + if (`SELECT COUNT(*)=1 FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'wsrep' AND PLUGIN_STATUS='ACTIVE'`) { if (`SELECT @@GLOBAL.WSREP_ON`) { --source include/galera_wait_ready.inc + --disable_query_log + --disable_result_log } } +# ..and returning original dirty read selection here +--eval SET wsrep_dirty_reads = $my_dirty_reads; + --enable_query_log --enable_result_log diff --git a/mysql-test/include/wsrep_wait_disconnect.inc b/mysql-test/include/wsrep_wait_disconnect.inc new file mode 100644 index 00000000000..740fc0d9426 --- /dev/null +++ b/mysql-test/include/wsrep_wait_disconnect.inc @@ -0,0 +1,20 @@ +let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready' AND VARIABLE_VALUE = 'OFF'; +# since this is called until AFTER provider disconnects,we need to allow +# queries in non-prim +# +# We are also forced to use a hard-coded value for wsrep_sync_wait here because +# we can not issue a SELECT query to obtain the original value and then restore +# it +disable_query_log; +SET SESSION wsrep_sync_wait = 7; +--let $restore_wsrep_on = `SHOW VARIABLES WHERE Variable_name = 'wsrep_on' AND Value = 'ON'` +SET SESSION wsrep_on = OFF; + +--source include/wait_condition.inc + +if ($restore_wsrep_on != "") +{ + --eval SET SESSION wsrep_on = ON +} +SET SESSION wsrep_sync_wait = 15; +enable_query_log; diff --git a/mysql-test/lib/My/ConfigFactory.pm b/mysql-test/lib/My/ConfigFactory.pm index 830b49d431f..f469cc9b062 100644 --- a/mysql-test/lib/My/ConfigFactory.pm +++ b/mysql-test/lib/My/ConfigFactory.pm @@ -206,7 +206,11 @@ my @mysqld_rules= { '#user' => sub { return shift->{ARGS}->{user} || ""; } }, { '#password' => sub { return shift->{ARGS}->{password} || ""; } }, { 'server-id' => \&fix_server_id, }, - { 'bind-address' => \&fix_bind_address }, + # + # bind-address is commented out here, because this would bind bind + # only 127.0.0.1 for mysqld, and in galera mtr testing we will need + # also 127.0.0.2 for sst address +# { 'bind-address' => \&fix_bind_address }, ); if (IS_WINDOWS) diff --git a/mysql-test/main/mysqld--help-notwin.result b/mysql-test/main/mysqld--help-notwin.result new file mode 100644 index 00000000000..b7db372a704 --- /dev/null +++ b/mysql-test/main/mysqld--help-notwin.result @@ -0,0 +1,1472 @@ +The following options may be given as the first argument: +--print-defaults Print the program argument list and exit. +--no-defaults Don't read default options from any option file, + except for login file. +--defaults-file=# Only read default options from the given file #. +--defaults-extra-file=# Read this file after the global files are read. +--defaults-group-suffix=# + Also read groups with concat(group, suffix) +--login-path=# Read this path from the login file. + + --abort-slave-event-count=# + Option used by mysql-test for debugging and testing of + replication. + --allow-suspicious-udfs + Allows use of UDFs consisting of only one symbol xxx() + without corresponding xxx_init() or xxx_deinit(). That + also means that one can load any function from any + library, for example exit() from libc.so + -a, --ansi Use ANSI SQL syntax instead of MySQL syntax. This mode + will also set transaction isolation level 'serializable'. + --auto-increment-increment[=#] + Auto-increment columns are incremented by this + --auto-increment-offset[=#] + Offset added to Auto-increment columns. Used when + auto-increment-increment != 1 + --autocommit Set default value for autocommit (0 or 1) + (Defaults to on; use --skip-autocommit to disable.) + --automatic-sp-privileges + Creating and dropping stored procedures alters ACLs + (Defaults to on; use --skip-automatic-sp-privileges to disable.) + --avoid-temporal-upgrade + When this option is enabled, the pre-5.6.4 temporal types + are not upgraded to the new format for ALTER TABLE + requests ADD/CHANGE/MODIFY COLUMN, ADD INDEX or FORCE + operation. This variable is deprecated and will be + removed in a future release. + --back-log=# The number of outstanding connection requests MySQL can + have. This comes into play when the main MySQL thread + gets very many connection requests in a very short time + -b, --basedir=name Path to installation directory. All paths are usually + resolved relative to this + --big-tables Allow big result sets by saving all temporary sets on + file (Solves most 'table full' errors) + --bind-address=name IP address to bind to. + --binlog-cache-size=# + The size of the transactional cache for updates to + transactional engines for the binary log. If you often + use transactions containing many statements, you can + increase this to get more performance + --binlog-checksum=name + Type of BINLOG_CHECKSUM_ALG. Include checksum for log + events in the binary log. Possible values are NONE and + CRC32; default is CRC32. + --binlog-direct-non-transactional-updates + Causes updates to non-transactional engines using + statement format to be written directly to binary log. + Before using this option make sure that there are no + dependencies between transactional and non-transactional + tables such as in the statement INSERT INTO t_myisam + SELECT * FROM t_innodb; otherwise, slaves may diverge + from the master. + --binlog-do-db=name Tells the master it should log updates for the specified + database, and exclude all others not explicitly + mentioned. + --binlog-error-action=name + When statements cannot be written to the binary log due + to a fatal error, the server can either ignore the error + and let the master continue, or abort. + --binlog-format=name + What form of binary logging the master will use: either + ROW for row-based binary logging, STATEMENT for + statement-based binary logging, or MIXED. MIXED is + statement-based binary logging except for those + statements where only row-based is correct: those which + involve user-defined functions (i.e. UDFs) or the UUID() + function; for those, row-based binary logging is + automatically used. If NDBCLUSTER is enabled and + binlog-format is MIXED, the format switches to row-based + and back implicitly per each query accessing an + NDBCLUSTER table + --binlog-gtid-simple-recovery + If this option is enabled, the server does not open more + than two binary logs when initializing GTID_PURGED and + GTID_EXECUTED, either during server restart or when + binary logs are being purged. Enabling this option is + useful when the server has already generated many binary + logs without GTID events (e.g., having GTID_MODE = OFF). + Note: If this option is enabled, GLOBAL.GTID_EXECUTED and + GLOBAL.GTID_PURGED may be initialized wrongly in two + cases: (1) GTID_MODE was ON for some binary logs but OFF + for the newest binary log. (2) SET GTID_PURGED was issued + after the oldest existing binary log was generated. If a + wrong set is computed in one of case (1) or case (2), it + will remain wrong even if the server is later restarted + with this option disabled. + --binlog-ignore-db=name + Tells the master that updates to the given database + should not be logged to the binary log. + --binlog-max-flush-queue-time=# + The maximum time that the binary log group commit will + keep reading transactions before it flush the + transactions to the binary log (and optionally sync, + depending on the value of sync_binlog). + --binlog-order-commits + Issue internal commit calls in the same order as + transactions are written to the binary log. Default is to + order commits. + (Defaults to on; use --skip-binlog-order-commits to disable.) + --binlog-row-event-max-size=# + The maximum size of a row-based binary log event in + bytes. Rows will be grouped into events smaller than this + size if possible. The value has to be a multiple of 256. + --binlog-row-image=name + Controls whether rows should be logged in 'FULL', + 'NOBLOB' or 'MINIMAL' formats. 'FULL', means that all + columns in the before and after image are logged. + 'NOBLOB', means that mysqld avoids logging blob columns + whenever possible (eg, blob column was not changed or is + not part of primary key). 'MINIMAL', means that a PK + equivalent (PK columns or full row if there is no PK in + the table) is logged in the before image, and only + changed columns are logged in the after image. (Default: + FULL). + --binlog-rows-query-log-events + Allow writing of Rows_query_log events into binary log. + --binlog-stmt-cache-size=# + The size of the statement cache for updates to + non-transactional engines for the binary log. If you + often use statements updating a great number of rows, you + can increase this to get more performance + --binlogging-impossible-mode=name + On a fatal error when statements cannot be binlogged the + behaviour can be ignore the error and let the master + continue or abort the server. This variable is deprecated + and will be removed in a future release. Please use + binlog_error_action instead. + --block-encryption-mode=name + mode for AES_ENCRYPT/AES_DECRYPT + --bootstrap Used by mysql installation scripts. + --bulk-insert-buffer-size=# + Size of tree cache used in bulk insert optimisation. Note + that this is a limit per thread! + --character-set-client-handshake + Don't ignore client side character set value sent during + handshake. + (Defaults to on; use --skip-character-set-client-handshake to disable.) + --character-set-filesystem=name + Set the filesystem character set. + -C, --character-set-server=name + Set the default character set. + --character-sets-dir=name + Directory where character sets are + -r, --chroot=name Chroot mysqld daemon during startup. + --collation-server=name + Set the default collation. + --completion-type=name + The transaction completion type, one of NO_CHAIN, CHAIN, + RELEASE + --concurrent-insert[=name] + Use concurrent insert with MyISAM. Possible values are + NEVER, AUTO, ALWAYS + --connect-timeout=# The number of seconds the mysqld server is waiting for a + connect packet before responding with 'Bad handshake' + --console Write error output on screen; don't remove the console + window on windows. + --core-file Write core on errors. + -h, --datadir=name Path to the database root directory + --date-format=name The DATE format (ignored) + --datetime-format=name + The DATETIME format (ignored) + --default-authentication-plugin=name + Defines what password- and authentication algorithm to + use per default + --default-storage-engine=name + The default storage engine for new tables + --default-time-zone=name + Set the default time zone. + --default-tmp-storage-engine=name + The default storage engine for new explict temporary + tables + --default-week-format=# + The default week format used by WEEK() functions + --delay-key-write[=name] + Type of DELAY_KEY_WRITE + --delayed-insert-limit=# + After inserting delayed_insert_limit rows, the INSERT + DELAYED handler will check if there are any SELECT + statements pending. If so, it allows these to execute + before continuing. This variable is deprecated along with + INSERT DELAYED. + --delayed-insert-timeout=# + How long a INSERT DELAYED thread should wait for INSERT + statements before terminating.This variable is deprecated + along with INSERT DELAYED. + --delayed-queue-size=# + What size queue (in rows) should be allocated for + handling INSERT DELAYED. If the queue becomes full, any + client that does INSERT DELAYED will wait until there is + room in the queue again.This variable is deprecated along + with INSERT DELAYED. + --disconnect-on-expired-password + Give clients that don't signal password expiration + support execution time error(s) instead of connection + error + (Defaults to on; use --skip-disconnect-on-expired-password to disable.) + --disconnect-slave-event-count=# + Option used by mysql-test for debugging and testing of + replication. + --div-precision-increment=# + Precision of the result of '/' operator will be increased + on that value + --end-markers-in-json + In JSON output ("EXPLAIN FORMAT=JSON" and optimizer + trace), if variable is set to 1, repeats the structure's + key (if it has one) near the closing bracket + --enforce-gtid-consistency + Prevents execution of statements that would be impossible + to log in a transactionally safe manner. Currently, the + disallowed statements include CREATE TEMPORARY TABLE + inside transactions, all updates to non-transactional + tables, and CREATE TABLE ... SELECT. + --eq-range-index-dive-limit=# + The optimizer will use existing index statistics instead + of doing index dives for equality ranges if the number of + equality ranges for the index is larger than or equal to + this number. If set to 0, index dives are always used. + --event-scheduler[=name] + Enable the event scheduler. Possible values are ON, OFF, + and DISABLED (keep the event scheduler completely + deactivated, it cannot be activated run-time) + -T, --exit-info[=#] Used for debugging. Use at your own risk. + --expire-logs-days=# + If non-zero, binary logs will be purged after + expire_logs_days days; possible purges happen at startup + and at binary log rotation + --explicit-defaults-for-timestamp + This option causes CREATE TABLE to create all TIMESTAMP + columns as NULL with DEFAULT NULL attribute, Without this + option, TIMESTAMP columns are NOT NULL and have implicit + DEFAULT clauses. The old behavior is deprecated. + --external-locking Use system (external) locking (disabled by default). + With this option enabled you can run myisamchk to test + (not repair) tables while the MySQL server is running. + Disable with --skip-external-locking. + --flush Flush MyISAM tables to disk between SQL commands + --flush-time=# A dedicated thread is created to flush all tables at the + given interval + --ft-boolean-syntax=name + List of operators for MATCH ... AGAINST ( ... IN BOOLEAN + MODE) + --ft-max-word-len=# The maximum length of the word to be included in a + FULLTEXT index. Note: FULLTEXT indexes must be rebuilt + after changing this variable + --ft-min-word-len=# The minimum length of the word to be included in a + FULLTEXT index. Note: FULLTEXT indexes must be rebuilt + after changing this variable + --ft-query-expansion-limit=# + Number of best matches to use for query expansion + --ft-stopword-file=name + Use stopwords from this file instead of built-in list + --gdb Set up signals usable for debugging. + --general-log Log connections and queries to a table or log file. + Defaults logging to a file hostname.log or a table + mysql.general_logif --log-output=TABLE is used + --general-log-file=name + Log connections and queries to given file + --group-concat-max-len=# + The maximum length of the result of function + GROUP_CONCAT() + --gtid-mode=name Whether Global Transaction Identifiers (GTIDs) are + enabled. Can be ON or OFF. + -?, --help Display this help and exit. + --host-cache-size=# How many host names should be cached to avoid resolving. + --ignore-builtin-innodb + IGNORED. This option will be removed in future releases. + Disable initialization of builtin InnoDB plugin + --ignore-db-dir=name + Specifies a directory to add to the ignore list when + collecting database names from the datadir. Put a blank + argument to reset the list accumulated so far. + --init-connect=name Command(s) that are executed for each new connection + --init-file=name Read SQL commands from this file at startup + --init-slave=name Command(s) that are executed by a slave server each time + the SQL thread starts + --interactive-timeout=# + The number of seconds the server waits for activity on an + interactive connection before closing it + --join-buffer-size=# + The size of the buffer that is used for full joins + --keep-files-on-create + Don't overwrite stale .MYD and .MYI even if no directory + is specified + --key-buffer-size=# The size of the buffer used for index blocks for MyISAM + tables. Increase this to get better index handling (for + all reads and multiple writes) to as much as you can + afford + --key-cache-age-threshold=# + This characterizes the number of hits a hot block has to + be untouched until it is considered aged enough to be + downgraded to a warm block. This specifies the percentage + ratio of that number of hits to the total number of + blocks in key cache + --key-cache-block-size=# + The default size of key cache blocks + --key-cache-division-limit=# + The minimum percentage of warm blocks in key cache + -L, --language=name Client error messages in given language. May be given as + a full path. Deprecated. Use --lc-messages-dir instead. + --large-pages Enable support for large pages + --lc-messages=name Set the language used for the error messages. + --lc-messages-dir=name + Directory where error messages are + --lc-time-names=name + Set the language used for the month names and the days of + the week. + --local-infile Enable LOAD DATA LOCAL INFILE + (Defaults to on; use --skip-local-infile to disable.) + --lock-wait-timeout=# + Timeout in seconds to wait for a lock before returning an + error. + --log-bin[=name] Log update queries in binary format. Optional (but + strongly recommended to avoid replication problems if + server's hostname changes) argument should be the chosen + location for the binary log files. + --log-bin-index=name + File that holds the names for binary log files. + --log-bin-trust-function-creators + If set to FALSE (the default), then when --log-bin is + used, creation of a stored function (or trigger) is + allowed only to users having the SUPER privilege and only + if this stored function (trigger) may not break binary + logging. Note that if ALL connections to this server + ALWAYS use row-based binary logging, the security issues + do not exist and the binary logging cannot break, so you + can safely set this to TRUE + --log-bin-use-v1-row-events + If equal to 1 then version 1 row events are written to a + row based binary log. If equal to 0, then the latest + version of events are written. This option is useful + during some upgrades. + --log-error[=name] Error log file + --log-isam[=name] Log all MyISAM changes to file. + --log-output=name Syntax: log-output=value[,value...], where "value" could + be TABLE, FILE or NONE + --log-queries-not-using-indexes + Log queries that are executed without benefit of any + index to the slow log if it is open + --log-raw Log to general log before any rewriting of the query. For + use in debugging, not production as sensitive information + may be logged. + --log-short-format Don't log extra information to update and slow-query + logs. + --log-slave-updates Tells the slave to log the updates from the slave thread + to the binary log. You will need to turn it on if you + plan to daisy-chain the slaves + --log-slow-admin-statements + Log slow OPTIMIZE, ANALYZE, ALTER and other + administrative statements to the slow log if it is open. + --log-slow-slave-statements + Log slow statements executed by slave thread to the slow + log if it is open. + --log-tc=name Path to transaction coordinator log (used for + transactions that affect more than one storage engine, + when binary log is disabled). + --log-tc-size=# Size of transaction coordinator log. + --log-throttle-queries-not-using-indexes[=#] + Log at most this many 'not using index' warnings per + minute to the slow log. Any further warnings will be + condensed into a single summary line. A value of 0 + disables throttling. Option has no effect unless + --log_queries_not_using_indexes is set. + -W, --log-warnings[=#] + Log some not critical warnings to the log file + --long-query-time=# Log all queries that have taken more than long_query_time + seconds to execute to file. The argument will be treated + as a decimal value with microsecond precision + --low-priority-updates + INSERT/DELETE/UPDATE has lower priority than selects + --lower-case-table-names[=#] + If set to 1 table names are stored in lowercase on disk + and table names will be case-insensitive. Should be set + to 2 if you are using a case insensitive file system + --master-info-file=name + The location and name of the file that remembers the + master and where the I/O replication thread is in the + master's binlogs. + --master-info-repository=name + Defines the type of the repository for the master + information. + --master-retry-count=# + The number of tries the slave will make to connect to the + master before giving up. Deprecated option, use 'CHANGE + MASTER TO master_retry_count = <num>' instead. + --master-verify-checksum + Force checksum verification of logged events in binary + log before sending them to slaves or printing them in + output of SHOW BINLOG EVENTS. Disabled by default. + --max-allowed-packet=# + Max packet length to send to or receive from the server + --max-binlog-cache-size=# + Sets the total size of the transactional cache + --max-binlog-dump-events=# + Option used by mysql-test for debugging and testing of + replication. + --max-binlog-size=# Binary log will be rotated automatically when the size + exceeds this value. Will also apply to relay logs if + max_relay_log_size is 0 + --max-binlog-stmt-cache-size=# + Sets the total size of the statement cache + --max-connect-errors=# + If there is more than this number of interrupted + connections from a host this host will be blocked from + further connections + --max-connections=# The number of simultaneous clients allowed + --max-delayed-threads=# + Don't start more than this number of threads to handle + INSERT DELAYED statements. If set to zero INSERT DELAYED + will be not used.This variable is deprecated along with + INSERT DELAYED. + --max-digest-length=# + Maximum length considered for digest text. + --max-error-count=# Max number of errors/warnings to store for a statement + --max-heap-table-size=# + Don't allow creation of heap tables bigger than this + --max-join-size=# Joins that are probably going to read more than + max_join_size records return an error + --max-length-for-sort-data=# + Max number of bytes in sorted records + --max-prepared-stmt-count=# + Maximum number of prepared statements in the server + --max-relay-log-size=# + If non-zero: relay log will be rotated automatically when + the size exceeds this value; if zero: when the size + exceeds max_binlog_size + --max-seeks-for-key=# + Limit assumed max number of seeks when looking up rows + based on a key + --max-sort-length=# The number of bytes to use when sorting BLOB or TEXT + values (only the first max_sort_length bytes of each + value are used; the rest are ignored) + --max-sp-recursion-depth[=#] + Maximum stored procedure recursion depth + --max-tmp-tables=# Maximum number of temporary tables a client can keep open + at a time + --max-user-connections=# + The maximum number of active connections for a single + user (0 = no limit) + --max-write-lock-count=# + After this many write locks, allow some read locks to run + in between + --memlock Lock mysqld in memory. + --metadata-locks-cache-size=# + Size of unused metadata locks cache + --metadata-locks-hash-instances=# + Number of metadata locks hash instances + --min-examined-row-limit=# + Don't write queries to slow log that examine fewer rows + than that + --multi-range-count=# + Number of key ranges to request at once. This variable + has no effect, and is deprecated. It will be removed in a + future release. + --myisam-block-size=# + Block size to be used for MyISAM index pages + --myisam-data-pointer-size=# + Default pointer size to be used for MyISAM tables + --myisam-max-sort-file-size=# + Don't use the fast sort index method to created index if + the temporary file would get bigger than this + --myisam-mmap-size=# + Restricts the total memory used for memory mapping of + MySQL tables + --myisam-recover-options[=name] + Syntax: myisam-recover-options[=option[,option...]], + where option can be DEFAULT, BACKUP, FORCE, QUICK, or OFF + --myisam-repair-threads=# + If larger than 1, when repairing a MyISAM table all + indexes will be created in parallel, with one thread per + index. The value of 1 disables parallel repair + --myisam-sort-buffer-size=# + The buffer that is allocated when sorting the index when + doing a REPAIR or when creating indexes with CREATE INDEX + or ALTER TABLE + --myisam-stats-method=name + Specifies how MyISAM index statistics collection code + should treat NULLs. Possible values of name are + NULLS_UNEQUAL (default behavior for 4.1 and later), + NULLS_EQUAL (emulate 4.0 behavior), and NULLS_IGNORED + --myisam-use-mmap Use memory mapping for reading and writing MyISAM tables + --net-buffer-length=# + Buffer length for TCP/IP and socket communication + --net-read-timeout=# + Number of seconds to wait for more data from a connection + before aborting the read + --net-retry-count=# If a read on a communication port is interrupted, retry + this many times before giving up + --net-write-timeout=# + Number of seconds to wait for a block to be written to a + connection before aborting the write + -n, --new Use very new possible "unsafe" functions + --old Use compatible behavior + --old-alter-table Use old, non-optimized alter table + --old-passwords=# Determine which hash algorithm to use when generating + passwords using the PASSWORD() function + --old-style-user-limits + Enable old-style user limits (before 5.0.3, user + resources were counted per each user+host vs. per + account). + --open-files-limit=# + If this is not 0, then mysqld will use this value to + reserve file descriptors to use with setrlimit(). If this + value is 0 then mysqld will reserve max_connections*5 or + max_connections + table_open_cache*2 (whichever is + larger) number of file descriptors + --optimizer-prune-level=# + Controls the heuristic(s) applied during query + optimization to prune less-promising partial plans from + the optimizer search space. Meaning: 0 - do not apply any + heuristic, thus perform exhaustive search; 1 - prune + plans based on number of retrieved rows + --optimizer-search-depth=# + Maximum depth of search performed by the query optimizer. + Values larger than the number of relations in a query + result in better query plans, but take longer to compile + a query. Values smaller than the number of tables in a + relation result in faster optimization, but may produce + very bad query plans. If set to 0, the system will + automatically pick a reasonable value + --optimizer-switch=name + optimizer_switch=option=val[,option=val...], where option + is one of {index_merge, index_merge_union, + index_merge_sort_union, index_merge_intersection, + engine_condition_pushdown, index_condition_pushdown, mrr, + mrr_cost_based, materialization, semijoin, loosescan, + firstmatch, subquery_materialization_cost_based, + block_nested_loop, batched_key_access, + use_index_extensions} and val is one of {on, off, + default} + --optimizer-trace=name + Controls tracing of the Optimizer: + optimizer_trace=option=val[,option=val...], where option + is one of {enabled, one_line} and val is one of {on, + default} + --optimizer-trace-features=name + Enables/disables tracing of selected features of the + Optimizer: + optimizer_trace_features=option=val[,option=val...], + where option is one of {greedy_search, range_optimizer, + dynamic_range, repeated_subselect} and val is one of {on, + off, default} + --optimizer-trace-limit=# + Maximum number of shown optimizer traces + --optimizer-trace-max-mem-size=# + Maximum allowed cumulated size of stored optimizer traces + --optimizer-trace-offset=# + Offset of first optimizer trace to show; see manual + --performance-schema + Enable the performance schema. + (Defaults to on; use --skip-performance-schema to disable.) + --performance-schema-accounts-size=# + Maximum number of instrumented user@host accounts. Use 0 + to disable, -1 for automated sizing. + --performance-schema-consumer-events-stages-current + Default startup value for the events_stages_current + consumer. + --performance-schema-consumer-events-stages-history + Default startup value for the events_stages_history + consumer. + --performance-schema-consumer-events-stages-history-long + Default startup value for the events_stages_history_long + consumer. + --performance-schema-consumer-events-statements-current + Default startup value for the events_statements_current + consumer. + (Defaults to on; use --skip-performance-schema-consumer-events-statements-current to disable.) + --performance-schema-consumer-events-statements-history + Default startup value for the events_statements_history + consumer. + --performance-schema-consumer-events-statements-history-long + Default startup value for the + events_statements_history_long consumer. + --performance-schema-consumer-events-waits-current + Default startup value for the events_waits_current + consumer. + --performance-schema-consumer-events-waits-history + Default startup value for the events_waits_history + consumer. + --performance-schema-consumer-events-waits-history-long + Default startup value for the events_waits_history_long + consumer. + --performance-schema-consumer-global-instrumentation + Default startup value for the global_instrumentation + consumer. + (Defaults to on; use --skip-performance-schema-consumer-global-instrumentation to disable.) + --performance-schema-consumer-statements-digest + Default startup value for the statements_digest consumer. + (Defaults to on; use --skip-performance-schema-consumer-statements-digest to disable.) + --performance-schema-consumer-thread-instrumentation + Default startup value for the thread_instrumentation + consumer. + (Defaults to on; use --skip-performance-schema-consumer-thread-instrumentation to disable.) + --performance-schema-digests-size=# + Size of the statement digest. Use 0 to disable, -1 for + automated sizing. + --performance-schema-events-stages-history-long-size=# + Number of rows in EVENTS_STAGES_HISTORY_LONG. Use 0 to + disable, -1 for automated sizing. + --performance-schema-events-stages-history-size=# + Number of rows per thread in EVENTS_STAGES_HISTORY. Use 0 + to disable, -1 for automated sizing. + --performance-schema-events-statements-history-long-size=# + Number of rows in EVENTS_STATEMENTS_HISTORY_LONG. Use 0 + to disable, -1 for automated sizing. + --performance-schema-events-statements-history-size=# + Number of rows per thread in EVENTS_STATEMENTS_HISTORY. + Use 0 to disable, -1 for automated sizing. + --performance-schema-events-waits-history-long-size=# + Number of rows in EVENTS_WAITS_HISTORY_LONG. Use 0 to + disable, -1 for automated sizing. + --performance-schema-events-waits-history-size=# + Number of rows per thread in EVENTS_WAITS_HISTORY. Use 0 + to disable, -1 for automated sizing. + --performance-schema-hosts-size=# + Maximum number of instrumented hosts. Use 0 to disable, + -1 for automated sizing. + --performance-schema-instrument[=name] + Default startup value for a performance schema + instrument. + --performance-schema-max-cond-classes=# + Maximum number of condition instruments. + --performance-schema-max-cond-instances=# + Maximum number of instrumented condition objects. Use 0 + to disable, -1 for automated sizing. + --performance-schema-max-digest-length=# + Maximum length considered for digest text, when stored in + performance_schema tables. + --performance-schema-max-file-classes=# + Maximum number of file instruments. + --performance-schema-max-file-handles=# + Maximum number of opened instrumented files. + --performance-schema-max-file-instances=# + Maximum number of instrumented files. Use 0 to disable, + -1 for automated sizing. + --performance-schema-max-mutex-classes=# + Maximum number of mutex instruments. + --performance-schema-max-mutex-instances=# + Maximum number of instrumented MUTEX objects. Use 0 to + disable, -1 for automated sizing. + --performance-schema-max-rwlock-classes=# + Maximum number of rwlock instruments. + --performance-schema-max-rwlock-instances=# + Maximum number of instrumented RWLOCK objects. Use 0 to + disable, -1 for automated sizing. + --performance-schema-max-socket-classes=# + Maximum number of socket instruments. + --performance-schema-max-socket-instances=# + Maximum number of opened instrumented sockets. Use 0 to + disable, -1 for automated sizing. + --performance-schema-max-stage-classes=# + Maximum number of stage instruments. + --performance-schema-max-statement-classes=# + Maximum number of statement instruments. + --performance-schema-max-table-handles=# + Maximum number of opened instrumented tables. Use 0 to + disable, -1 for automated sizing. + --performance-schema-max-table-instances=# + Maximum number of instrumented tables. Use 0 to disable, + -1 for automated sizing. + --performance-schema-max-thread-classes=# + Maximum number of thread instruments. + --performance-schema-max-thread-instances=# + Maximum number of instrumented threads. Use 0 to disable, + -1 for automated sizing. + --performance-schema-session-connect-attrs-size=# + Size of session attribute string buffer per thread. Use 0 + to disable, -1 for automated sizing. + --performance-schema-setup-actors-size=# + Maximum number of rows in SETUP_ACTORS. + --performance-schema-setup-objects-size=# + Maximum number of rows in SETUP_OBJECTS. + --performance-schema-users-size=# + Maximum number of instrumented users. Use 0 to disable, + -1 for automated sizing. + --pid-file=name Pid file used by safe_mysqld + --plugin-dir=name Directory for plugins + --plugin-load=name Optional semicolon-separated list of plugins to load, + where each plugin is identified as name=library, where + name is the plugin name and library is the plugin library + in plugin_dir. + --plugin-load-add=name + Optional semicolon-separated list of plugins to load, + where each plugin is identified as name=library, where + name is the plugin name and library is the plugin library + in plugin_dir. This option adds to the list speficied by + --plugin-load in an incremental way. Multiple + --plugin-load-add are supported. + -P, --port=# Port number to use for connection or 0 to default to, + my.cnf, $MYSQL_TCP_PORT, /etc/services, built-in default + (3306), whatever comes first + --port-open-timeout=# + Maximum time in seconds to wait for the port to become + free. (Default: No wait). + --preload-buffer-size=# + The size of the buffer that is allocated when preloading + indexes + --profiling-history-size=# + Limit of query profiling memory + --query-alloc-block-size=# + Allocation block size for query parsing and execution + --query-cache-limit=# + Don't cache results that are bigger than this + --query-cache-min-res-unit=# + The minimum size for blocks allocated by the query cache + --query-cache-size=# + The memory allocated to store results from old queries + --query-cache-type=name + OFF = Don't cache or retrieve results. ON = Cache all + results except SELECT SQL_NO_CACHE ... queries. DEMAND = + Cache only SELECT SQL_CACHE ... queries + --query-cache-wlock-invalidate + Invalidate queries in query cache on LOCK for write + --query-prealloc-size=# + Persistent buffer for query parsing and execution + --range-alloc-block-size=# + Allocation block size for storing ranges during + optimization + --read-buffer-size=# + Each thread that does a sequential scan allocates a + buffer of this size for each table it scans. If you do + many sequential scans, you may want to increase this + value + --read-only Make all non-temporary tables read-only, with the + exception for replication (slave) threads and users with + the SUPER privilege + --read-rnd-buffer-size=# + When reading rows in sorted order after a sort, the rows + are read through this buffer to avoid a disk seeks + --relay-log=name The location and name to use for relay logs + --relay-log-index=name + File that holds the names for relay log files. + --relay-log-info-file=name + The location and name of the file that remembers where + the SQL replication thread is in the relay logs + --relay-log-info-repository=name + Defines the type of the repository for the relay log + information and associated workers. + --relay-log-purge if disabled - do not purge relay logs. if enabled - purge + them as soon as they are no more needed + (Defaults to on; use --skip-relay-log-purge to disable.) + --relay-log-recovery + Enables automatic relay log recovery right after the + database startup, which means that the IO Thread starts + re-fetching from the master right after the last + transaction processed + --relay-log-space-limit=# + Maximum space to use for all relay logs + --replicate-do-db=name + Tells the slave thread to restrict replication to the + specified database. To specify more than one database, + use the directive multiple times, once for each database. + Note that this will only work if you do not use + cross-database queries such as UPDATE some_db.some_table + SET foo='bar' while having selected a different or no + database. If you need cross database updates to work, + make sure you have 3.23.28 or later, and use + replicate-wild-do-table=db_name.%. + --replicate-do-table=name + Tells the slave thread to restrict replication to the + specified table. To specify more than one table, use the + directive multiple times, once for each table. This will + work for cross-database updates, in contrast to + replicate-do-db. + --replicate-ignore-db=name + Tells the slave thread to not replicate to the specified + database. To specify more than one database to ignore, + use the directive multiple times, once for each database. + This option will not work if you use cross database + updates. If you need cross database updates to work, make + sure you have 3.23.28 or later, and use + replicate-wild-ignore-table=db_name.%. + --replicate-ignore-table=name + Tells the slave thread to not replicate to the specified + table. To specify more than one table to ignore, use the + directive multiple times, once for each table. This will + work for cross-database updates, in contrast to + replicate-ignore-db. + --replicate-rewrite-db=name + Updates to a database with a different name than the + original. Example: + replicate-rewrite-db=master_db_name->slave_db_name. + --replicate-same-server-id + In replication, if set to 1, do not skip events having + our server id. Default value is 0 (to break infinite + loops in circular replication). Can't be set to 1 if + --log-slave-updates is used. + --replicate-wild-do-table=name + Tells the slave thread to restrict replication to the + tables that match the specified wildcard pattern. To + specify more than one table, use the directive multiple + times, once for each table. This will work for + cross-database updates. Example: + replicate-wild-do-table=foo%.bar% will replicate only + updates to tables in all databases that start with foo + and whose table names start with bar. + --replicate-wild-ignore-table=name + Tells the slave thread to not replicate to the tables + that match the given wildcard pattern. To specify more + than one table to ignore, use the directive multiple + times, once for each table. This will work for + cross-database updates. Example: + replicate-wild-ignore-table=foo%.bar% will not do updates + to tables in databases that start with foo and whose + table names start with bar. + --report-host=name Hostname or IP of the slave to be reported to the master + during slave registration. Will appear in the output of + SHOW SLAVE HOSTS. Leave unset if you do not want the + slave to register itself with the master. Note that it is + not sufficient for the master to simply read the IP of + the slave off the socket once the slave connects. Due to + NAT and other routing issues, that IP may not be valid + for connecting to the slave from the master or other + hosts + --report-password=name + The account password of the slave to be reported to the + master during slave registration + --report-port=# Port for connecting to slave reported to the master + during slave registration. Set it only if the slave is + listening on a non-default port or if you have a special + tunnel from the master or other clients to the slave. If + not sure, leave this option unset + --report-user=name The account user name of the slave to be reported to the + master during slave registration + --rpl-stop-slave-timeout=# + Timeout in seconds to wait for slave to stop before + returning a warning. + --safe-user-create Don't allow new user creation by the user who has no + write privileges to the mysql.user table. + --secure-auth Disallow authentication for accounts that have old + (pre-4.1) passwords + (Defaults to on; use --skip-secure-auth to disable.) + --secure-file-priv=name + Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to + files within specified directory + --server-id=# Uniquely identifies the server instance in the community + of replication partners + --server-id-bits=# Set number of significant bits in server-id + --show-old-temporals + When this option is enabled, the pre-5.6.4 temporal types + will be marked in the 'SHOW CREATE TABLE' and + 'INFORMATION_SCHEMA.COLUMNS' table as a comment in + COLUMN_TYPE field. This variable is deprecated and will + be removed in a future release. + --show-slave-auth-info + Show user and password in SHOW SLAVE HOSTS on this + master. + --simplified-binlog-gtid-recovery + Alias for @@binlog_gtid_simple_recovery. Deprecated + --skip-grant-tables Start without grant tables. This gives all users FULL + ACCESS to all tables. + --skip-host-cache Don't cache host names. + --skip-name-resolve Don't resolve hostnames. All hostnames are IP's or + 'localhost'. + --skip-networking Don't allow connection with TCP/IP + --skip-new Don't use new, possibly wrong routines. + --skip-show-database + Don't allow 'SHOW DATABASE' commands + --skip-slave-start If set, slave is not autostarted. + --skip-stack-trace Don't print a stack trace on failure. + --slave-allow-batching + Allow slave to batch requests + --slave-checkpoint-group=# + Maximum number of processed transactions by + Multi-threaded slave before a checkpoint operation is + called to update progress status. + --slave-checkpoint-period=# + Gather workers' activities to Update progress status of + Multi-threaded slave and flush the relay log info to disk + after every #th milli-seconds. + --slave-compressed-protocol + Use compression on master/slave protocol + --slave-exec-mode=name + Modes for how replication events should be executed. + Legal values are STRICT (default) and IDEMPOTENT. In + IDEMPOTENT mode, replication will not stop for operations + that are idempotent. In STRICT mode, replication will + stop on any unexpected difference between the master and + the slave + --slave-load-tmpdir=name + The location where the slave should put its temporary + files when replicating a LOAD DATA INFILE command + --slave-max-allowed-packet=# + The maximum packet length to sent successfully from the + master to slave. + --slave-net-timeout=# + Number of seconds to wait for more data from a + master/slave connection before aborting the read + --slave-parallel-workers=# + Number of worker threads for executing events in parallel + --slave-pending-jobs-size-max=# + Max size of Slave Worker queues holding yet not applied + events.The least possible value must be not less than the + master side max_allowed_packet. + --slave-rows-search-algorithms=name + Set of searching algorithms that the slave will use while + searching for records from the storage engine to either + updated or deleted them. Possible values are: INDEX_SCAN, + TABLE_SCAN and HASH_SCAN. Any combination is allowed, and + the slave will always pick the most suitable algorithm + for any given scenario. (Default: INDEX_SCAN, + TABLE_SCAN). + --slave-skip-errors=name + Tells the slave thread to continue replication when a + query event returns an error from the provided list + --slave-sql-verify-checksum + Force checksum verification of replication events after + reading them from relay log. Note: Events are always + checksum-verified by slave on receiving them from the + network before writing them to the relay log. Enabled by + default. + (Defaults to on; use --skip-slave-sql-verify-checksum to disable.) + --slave-transaction-retries=# + Number of times the slave SQL thread will retry a + transaction in case it failed with a deadlock or elapsed + lock wait timeout, before giving up and stopping + --slave-type-conversions=name + Set of slave type conversions that are enabled. Legal + values are: ALL_LOSSY to enable lossy conversions, + ALL_NON_LOSSY to enable non-lossy conversions, + ALL_UNSIGNED to treat all integer column type data to be + unsigned values, and ALL_SIGNED to treat all integer + column type data to be signed values. Default treatment + is ALL_SIGNED. If ALL_SIGNED and ALL_UNSIGNED both are + specifed, ALL_SIGNED will take high priority than + ALL_UNSIGNED. If the variable is assigned the empty set, + no conversions are allowed and it is expected that the + types match exactly. + --slow-launch-time=# + If creating the thread takes longer than this value (in + seconds), the Slow_launch_threads counter will be + incremented + --slow-query-log Log slow queries to a table or log file. Defaults logging + to a file hostname-slow.log or a table mysql.slow_log if + --log-output=TABLE is used. Must be enabled to activate + other slow log options + --slow-query-log-file=name + Log slow queries to given log file. Defaults logging to + hostname-slow.log. Must be enabled to activate other slow + log options + --socket=name Socket file to use for connection + --sort-buffer-size=# + Each thread that needs to do a sort allocates a buffer of + this size + --sporadic-binlog-dump-fail + Option used by mysql-test for debugging and testing of + replication. + --sql-mode=name Syntax: sql-mode=mode[,mode[,mode...]]. See the manual + for the complete list of valid sql modes + --stored-program-cache=# + The soft upper limit for number of cached stored routines + for one connection. + -s, --symbolic-links + Enable symbolic link support. + --sync-binlog=# Synchronously flush binary log to disk after every #th + write to the file. Use 0 (default) to disable synchronous + flushing + --sync-frm Sync .frm files to disk on creation + (Defaults to on; use --skip-sync-frm to disable.) + --sync-master-info=# + Synchronously flush master info to disk after every #th + event. Use 0 to disable synchronous flushing + --sync-relay-log=# Synchronously flush relay log to disk after every #th + event. Use 0 to disable synchronous flushing + --sync-relay-log-info=# + Synchronously flush relay log info to disk after every + #th transaction. Use 0 to disable synchronous flushing + --sysdate-is-now Non-default option to alias SYSDATE() to NOW() to make it + safe-replicable. Since 5.0, SYSDATE() returns a `dynamic' + value different for different invocations, even within + the same statement. + --table-definition-cache=# + The number of cached table definitions + --table-open-cache=# + The number of cached open tables (total for all table + cache instances) + --table-open-cache-instances=# + The number of table cache instances + --tc-heuristic-recover=name + Decision to use in heuristic recover process. Possible + values are COMMIT or ROLLBACK. + --thread-cache-size=# + How many threads we should keep in a cache for reuse + --thread-handling=name + Define threads usage for handling queries, one of + one-thread-per-connection, no-threads, loaded-dynamically + --thread-stack=# The stack size for each thread + --time-format=name The TIME format (ignored) + --timed-mutexes Specify whether to time mutexes. Deprecated, has no + effect. + --tmp-table-size=# If an internal in-memory temporary table exceeds this + size, MySQL will automatically convert it to an on-disk + MyISAM table + -t, --tmpdir=name Path for temporary files. Several paths may be specified, + separated by a colon (:), in this case they are used in a + round-robin fashion + --transaction-alloc-block-size=# + Allocation block size for transactions to be stored in + binary log + --transaction-isolation=name + Default transaction isolation level. + --transaction-prealloc-size=# + Persistent buffer for transactions to be stored in binary + log + --transaction-read-only + Default transaction access mode. True if transactions are + read-only. + --updatable-views-with-limit=name + YES = Don't issue an error message (warning only) if a + VIEW without presence of a key of the underlying table is + used in queries with a LIMIT clause for updating. NO = + Prohibit update of a VIEW, which does not contain a key + of the underlying table and the query uses a LIMIT clause + (usually get from GUI tools) + -u, --user=name Run mysqld daemon as user. + --validate-user-plugins + Turns on additional validation of authentication plugins + assigned to user accounts. + (Defaults to on; use --skip-validate-user-plugins to disable.) + -v, --verbose Used with --help option for detailed help. + -V, --version Output version information and exit. + --wait-timeout=# The number of seconds the server waits for activity on a + connection before closing it + --wsrep-OSU-method[=name] + Method for Online Schema Upgrade + --wsrep-SR-store=name + Storage for streaming replication fragments + --wsrep-auto-increment-control + To automatically control the assignment of autoincrement + variables + (Defaults to on; use --skip-wsrep-auto-increment-control to disable.) + --wsrep-causal-reads + (DEPRECATED) setting this variable is equivalent to + setting wsrep_sync_wait READ flag + --wsrep-certify-nonPK + Certify tables with no primary key + (Defaults to on; use --skip-wsrep-certify-nonPK to disable.) + --wsrep-cluster-address=name + Address to initially connect to cluster + --wsrep-cluster-name=name + Name for the cluster + --wsrep-convert-LOCK-to-trx + To convert locking sessions into transactions + --wsrep-data-home-dir=name + home directory for wsrep provider + --wsrep-dbug-option=name + DBUG options to provider library + --wsrep-debug To enable debug level logging + --wsrep-desync To desynchronize the node from the cluster + --wsrep-dirty-reads Allow reads from a node is not in primary component + --wsrep-drupal-282555-workaround + To use a workaround forbad autoincrement value + --wsrep-forced-binlog-format=name + binlog format to take effect over user's choice + --wsrep-ignore-apply-errors=# + Ignore replication errors + --wsrep-load-data-splitting + To commit LOAD DATA transaction after every 10K rows + inserted (deprecating) + (Defaults to on; use --skip-wsrep-load-data-splitting to disable.) + --wsrep-log-conflicts + To log multi-master conflicts + --wsrep-max-ws-rows=# + Max number of rows in write set + --wsrep-max-ws-size=# + Max write set size (bytes) + --wsrep-mysql-replication-bundle=# + mysql replication group commit + --wsrep-node-address=name + Node address + --wsrep-node-incoming-address=name + Client connection address + --wsrep-node-name=name + Node name + --wsrep-notify-cmd=name + --wsrep-on To enable wsrep replication + (Defaults to on; use --skip-wsrep-on to disable.) + --wsrep-preordered To enable preordered write set processing + --wsrep-provider=name + Path to replication provider library + --wsrep-provider-options=name + provider specific options + --wsrep-recover Recover database state after crash and exit + --wsrep-reject-queries[=name] + Variable to set to reject queries + --wsrep-replicate-myisam + To enable myisam replication + --wsrep-restart-slave + Should MySQL slave be restarted automatically, when node + joins back to cluster + --wsrep-retry-autocommit=# + Max number of times to retry a failed autocommit + statement + --wsrep-slave-FK-checks + Should slave thread do foreign key constraint checks + (Defaults to on; use --skip-wsrep-slave-FK-checks to disable.) + --wsrep-slave-UK-checks + Should slave thread do secondary index uniqueness checks + --wsrep-slave-threads=# + Number of slave appliers to launch + --wsrep-sst-auth=name + Authentication for SST connection + --wsrep-sst-donor=name + preferred donor node for the SST + --wsrep-sst-donor-rejects-queries + Reject client queries when donating state snapshot + transfer + --wsrep-sst-method=name + State snapshot transfer method + --wsrep-sst-receive-address=name + Address where node is waiting for SST contact + --wsrep-start-position=name + global transaction position to start from + --wsrep-sync-wait[=#] + Ensure "synchronous" read view before executing an + operation of the type specified by bitmask: 1 - + READ(includes SELECT, SHOW and BEGIN/START TRANSACTION); + 2 - UPDATE and DELETE; 4 - INSERT and REPLACE + --wsrep-trx-fragment-size=# + Size of transaction fragments for streaming replication + (measured in units of 'wsrep_trx_fragment_unit') + --wsrep-trx-fragment-unit=name + Unit for streaming replication transaction fragments' + size: bytes, events, rows, statements + +Variables (--variable-name=value) +abort-slave-event-count 0 +allow-suspicious-udfs FALSE +auto-increment-increment 1 +auto-increment-offset 1 +autocommit TRUE +automatic-sp-privileges TRUE +avoid-temporal-upgrade FALSE +back-log 80 +big-tables FALSE +bind-address * +binlog-cache-size 32768 +binlog-checksum CRC32 +binlog-direct-non-transactional-updates FALSE +binlog-error-action IGNORE_ERROR +binlog-format STATEMENT +binlog-gtid-simple-recovery FALSE +binlog-max-flush-queue-time 0 +binlog-order-commits TRUE +binlog-row-event-max-size 8192 +binlog-row-image FULL +binlog-rows-query-log-events FALSE +binlog-stmt-cache-size 32768 +binlogging-impossible-mode IGNORE_ERROR +block-encryption-mode aes-128-ecb +bulk-insert-buffer-size 8388608 +character-set-client-handshake TRUE +character-set-filesystem binary +character-set-server latin1 +character-sets-dir MYSQL_CHARSETSDIR/ +chroot (No default value) +collation-server latin1_swedish_ci +completion-type NO_CHAIN +concurrent-insert AUTO +connect-timeout 10 +console FALSE +date-format %Y-%m-%d +datetime-format %Y-%m-%d %H:%i:%s +default-storage-engine InnoDB +default-time-zone (No default value) +default-tmp-storage-engine InnoDB +default-week-format 0 +delay-key-write ON +delayed-insert-limit 100 +delayed-insert-timeout 300 +delayed-queue-size 1000 +disconnect-on-expired-password TRUE +disconnect-slave-event-count 0 +div-precision-increment 4 +end-markers-in-json FALSE +enforce-gtid-consistency FALSE +eq-range-index-dive-limit 10 +event-scheduler OFF +expire-logs-days 0 +explicit-defaults-for-timestamp FALSE +external-locking FALSE +flush FALSE +flush-time 0 +ft-boolean-syntax + -><()~*:""&| +ft-max-word-len 84 +ft-min-word-len 4 +ft-query-expansion-limit 20 +ft-stopword-file (No default value) +gdb FALSE +general-log FALSE +group-concat-max-len 1024 +gtid-mode OFF +help TRUE +host-cache-size 279 +ignore-builtin-innodb FALSE +init-connect +init-file (No default value) +init-slave +interactive-timeout 28800 +join-buffer-size 262144 +keep-files-on-create FALSE +key-buffer-size 8388608 +key-cache-age-threshold 300 +key-cache-block-size 1024 +key-cache-division-limit 100 +language MYSQL_SHAREDIR/ +large-pages FALSE +lc-messages en_US +lc-messages-dir MYSQL_SHAREDIR/ +lc-time-names en_US +local-infile TRUE +lock-wait-timeout 31536000 +log-bin (No default value) +log-bin-index (No default value) +log-bin-trust-function-creators FALSE +log-bin-use-v1-row-events FALSE +log-error +log-isam myisam.log +log-output FILE +log-queries-not-using-indexes FALSE +log-raw FALSE +log-short-format FALSE +log-slave-updates FALSE +log-slow-admin-statements FALSE +log-slow-slave-statements FALSE +log-tc tc.log +log-tc-size 24576 +log-throttle-queries-not-using-indexes 0 +log-warnings 1 +long-query-time 10 +low-priority-updates FALSE +lower-case-table-names 1 +master-info-file master.info +master-info-repository FILE +master-retry-count 86400 +master-verify-checksum FALSE +max-allowed-packet 4194304 +max-binlog-cache-size 18446744073709547520 +max-binlog-dump-events 0 +max-binlog-size 1073741824 +max-binlog-stmt-cache-size 18446744073709547520 +max-connect-errors 100 +max-connections 151 +max-delayed-threads 20 +max-digest-length 1024 +max-error-count 64 +max-heap-table-size 16777216 +max-join-size 18446744073709551615 +max-length-for-sort-data 1024 +max-prepared-stmt-count 16382 +max-relay-log-size 0 +max-seeks-for-key 18446744073709551615 +max-sort-length 1024 +max-sp-recursion-depth 0 +max-tmp-tables 32 +max-user-connections 0 +max-write-lock-count 18446744073709551615 +memlock FALSE +metadata-locks-cache-size 1024 +metadata-locks-hash-instances 8 +min-examined-row-limit 0 +multi-range-count 256 +myisam-block-size 1024 +myisam-data-pointer-size 6 +myisam-max-sort-file-size 9223372036853727232 +myisam-mmap-size 18446744073709551615 +myisam-recover-options OFF +myisam-repair-threads 1 +myisam-sort-buffer-size 8388608 +myisam-stats-method nulls_unequal +myisam-use-mmap FALSE +net-buffer-length 16384 +net-read-timeout 30 +net-retry-count 10 +net-write-timeout 60 +new FALSE +old FALSE +old-alter-table FALSE +old-passwords 0 +old-style-user-limits FALSE +optimizer-prune-level 1 +optimizer-search-depth 62 +optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,mrr=on,mrr_cost_based=on,block_nested_loop=on,batched_key_access=off,materialization=on,semijoin=on,loosescan=on,firstmatch=on,subquery_materialization_cost_based=on,use_index_extensions=on +optimizer-trace +optimizer-trace-features greedy_search=on,range_optimizer=on,dynamic_range=on,repeated_subselect=on +optimizer-trace-limit 1 +optimizer-trace-max-mem-size 16384 +optimizer-trace-offset -1 +performance-schema TRUE +performance-schema-accounts-size -1 +performance-schema-consumer-events-stages-current FALSE +performance-schema-consumer-events-stages-history FALSE +performance-schema-consumer-events-stages-history-long FALSE +performance-schema-consumer-events-statements-current TRUE +performance-schema-consumer-events-statements-history FALSE +performance-schema-consumer-events-statements-history-long FALSE +performance-schema-consumer-events-waits-current FALSE +performance-schema-consumer-events-waits-history FALSE +performance-schema-consumer-events-waits-history-long FALSE +performance-schema-consumer-global-instrumentation TRUE +performance-schema-consumer-statements-digest TRUE +performance-schema-consumer-thread-instrumentation TRUE +performance-schema-digests-size -1 +performance-schema-events-stages-history-long-size -1 +performance-schema-events-stages-history-size -1 +performance-schema-events-statements-history-long-size -1 +performance-schema-events-statements-history-size -1 +performance-schema-events-waits-history-long-size -1 +performance-schema-events-waits-history-size -1 +performance-schema-hosts-size -1 +performance-schema-instrument +performance-schema-max-cond-classes 80 +performance-schema-max-cond-instances -1 +performance-schema-max-digest-length 1024 +performance-schema-max-file-classes 50 +performance-schema-max-file-handles 32768 +performance-schema-max-file-instances -1 +performance-schema-max-mutex-classes 200 +performance-schema-max-mutex-instances -1 +performance-schema-max-rwlock-classes 40 +performance-schema-max-rwlock-instances -1 +performance-schema-max-socket-classes 10 +performance-schema-max-socket-instances -1 +performance-schema-max-stage-classes 150 +performance-schema-max-statement-classes 168 +performance-schema-max-table-handles -1 +performance-schema-max-table-instances -1 +performance-schema-max-thread-classes 50 +performance-schema-max-thread-instances -1 +performance-schema-session-connect-attrs-size -1 +performance-schema-setup-actors-size 100 +performance-schema-setup-objects-size 100 +performance-schema-users-size -1 +port #### +port-open-timeout 0 +preload-buffer-size 32768 +profiling-history-size 15 +query-alloc-block-size 8192 +query-cache-limit 1048576 +query-cache-min-res-unit 4096 +query-cache-size 1048576 +query-cache-type OFF +query-cache-wlock-invalidate FALSE +query-prealloc-size 8192 +range-alloc-block-size 4096 +read-buffer-size 131072 +read-only FALSE +read-rnd-buffer-size 262144 +relay-log (No default value) +relay-log-index (No default value) +relay-log-info-file relay-log.info +relay-log-info-repository FILE +relay-log-purge TRUE +relay-log-recovery FALSE +relay-log-space-limit 0 +replicate-same-server-id FALSE +report-host (No default value) +report-password (No default value) +report-port 0 +report-user (No default value) +rpl-stop-slave-timeout 31536000 +safe-user-create FALSE +secure-auth TRUE +server-id 0 +server-id-bits 32 +show-old-temporals FALSE +show-slave-auth-info FALSE +simplified-binlog-gtid-recovery FALSE +skip-grant-tables TRUE +skip-name-resolve FALSE +skip-networking FALSE +skip-show-database FALSE +skip-slave-start FALSE +slave-allow-batching FALSE +slave-checkpoint-group 512 +slave-checkpoint-period 300 +slave-compressed-protocol FALSE +slave-exec-mode STRICT +slave-max-allowed-packet 1073741824 +slave-net-timeout 3600 +slave-parallel-workers 0 +slave-pending-jobs-size-max 16777216 +slave-rows-search-algorithms TABLE_SCAN,INDEX_SCAN +slave-skip-errors (No default value) +slave-sql-verify-checksum TRUE +slave-transaction-retries 10 +slave-type-conversions +slow-launch-time 2 +slow-query-log FALSE +sort-buffer-size 262144 +sporadic-binlog-dump-fail FALSE +sql-mode NO_ENGINE_SUBSTITUTION +stored-program-cache 256 +symbolic-links FALSE +sync-binlog 0 +sync-frm TRUE +sync-master-info 10000 +sync-relay-log 10000 +sync-relay-log-info 10000 +sysdate-is-now FALSE +table-open-cache-instances 1 +tc-heuristic-recover COMMIT +thread-cache-size 9 +thread-handling one-thread-per-connection +thread-stack 262144 +time-format %H:%i:%s +timed-mutexes FALSE +tmp-table-size 16777216 +transaction-alloc-block-size 8192 +transaction-isolation REPEATABLE-READ +transaction-prealloc-size 4096 +transaction-read-only FALSE +updatable-views-with-limit YES +validate-user-plugins TRUE +verbose TRUE +wait-timeout 28800 +wsrep-OSU-method TOI +wsrep-SR-store table +wsrep-auto-increment-control TRUE +wsrep-causal-reads FALSE +wsrep-certify-nonPK TRUE +wsrep-cluster-address +wsrep-cluster-name my_wsrep_cluster +wsrep-convert-LOCK-to-trx FALSE +wsrep-data-home-dir +wsrep-dbug-option +wsrep-debug FALSE +wsrep-desync FALSE +wsrep-dirty-reads FALSE +wsrep-drupal-282555-workaround FALSE +wsrep-forced-binlog-format NONE +wsrep-ignore-apply-errors 7 +wsrep-load-data-splitting TRUE +wsrep-log-conflicts FALSE +wsrep-max-ws-rows 0 +wsrep-max-ws-size 2147483647 +wsrep-mysql-replication-bundle 0 +wsrep-node-address +wsrep-node-incoming-address AUTO +wsrep-notify-cmd +wsrep-on FALSE +wsrep-preordered FALSE +wsrep-provider none +wsrep-provider-options +wsrep-recover FALSE +wsrep-reject-queries NONE +wsrep-replicate-myisam FALSE +wsrep-restart-slave FALSE +wsrep-retry-autocommit 1 +wsrep-slave-FK-checks TRUE +wsrep-slave-UK-checks FALSE +wsrep-slave-threads 1 +wsrep-sst-auth (No default value) +wsrep-sst-donor +wsrep-sst-donor-rejects-queries FALSE +wsrep-sst-method rsync +wsrep-sst-receive-address AUTO +wsrep-start-position 00000000-0000-0000-0000-000000000000:-1 +wsrep-sync-wait 0 +wsrep-trx-fragment-size 0 +wsrep-trx-fragment-unit bytes + +To see what values a running MySQL server is using, type +'mysqladmin variables' instead of 'mysqld --verbose --help'. diff --git a/mysql-test/main/query_cache_size_functionality.result b/mysql-test/main/query_cache_size_functionality.result new file mode 100644 index 00000000000..7563b3e61eb --- /dev/null +++ b/mysql-test/main/query_cache_size_functionality.result @@ -0,0 +1,226 @@ +'#________________________VAR_02_query_cache_size__________________#' +echo '##' +--echo '#---------------------WL6372_VAR_2_01----------------------#' +#################################################################### +# Checking default value # +#################################################################### +SELECT COUNT(@@GLOBAL.query_cache_size) +1 Expected +SELECT @@GLOBAL.query_cache_size; +@@GLOBAL.query_cache_size +1048576 +1048576 Expected +'#---------------------WL6372_VAR_2_02----------------------#' +# Restart server with query_cache_size 51200; +SELECT @@GLOBAL.query_cache_size; +@@GLOBAL.query_cache_size +51200 +51200 Expected +SET @@GLOBAL.query_cache_size=DEFAULT; +SELECT @@GLOBAL.query_cache_size; +@@GLOBAL.query_cache_size +1048576 +1048576 Expected +'#---------------------WL6372_VAR_2_03----------------------#' +SET @@local.query_cache_size=1; +ERROR HY000: Variable 'query_cache_size' is a GLOBAL variable and should be set with SET GLOBAL +Expected error 'Global variable' +SET @@session.query_cache_size=1; +ERROR HY000: Variable 'query_cache_size' is a GLOBAL variable and should be set with SET GLOBAL +Expected error 'Global variable' +SET @@GLOBAL.query_cache_size=1; +SET @@GLOBAL.query_cache_size=DEFAULT; +SELECT @@GLOBAL.query_cache_size; +@@GLOBAL.query_cache_size +1048576 +1048576 Expected +'#---------------------WL6372_VAR_2_04----------------------#' +SELECT @@GLOBAL.query_cache_size = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='query_cache_size'; +@@GLOBAL.query_cache_size = VARIABLE_VALUE +1 +1 Expected +SELECT COUNT(@@GLOBAL.query_cache_size); +COUNT(@@GLOBAL.query_cache_size) +1 +1 Expected +SELECT COUNT(VARIABLE_VALUE) +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='query_cache_size'; +COUNT(VARIABLE_VALUE) +1 +1 Expected +'#---------------------WL6372_VAR_2_05----------------------#' +SELECT @@query_cache_size = @@GLOBAL.query_cache_size; +@@query_cache_size = @@GLOBAL.query_cache_size +1 +1 Expected +SELECT COUNT(@@local.query_cache_size); +ERROR HY000: Variable 'query_cache_size' is a GLOBAL variable +Expected error 'Variable is a GLOBAL variable' +SELECT COUNT(@@SESSION.query_cache_size); +ERROR HY000: Variable 'query_cache_size' is a GLOBAL variable +Expected error 'Variable is a GLOBAL variable' +SELECT COUNT(@@GLOBAL.query_cache_size); +COUNT(@@GLOBAL.query_cache_size) +1 +1 Expected +SELECT query_cache_size = @@SESSION.query_cache_size; +ERROR 42S22: Unknown column 'query_cache_size' in 'field list' +Expected error 'Unknown column query_cache_size in field list' +'#---------------------WL6372_VAR_2_06----------------------#' +Check the size of the vardir +The output size is in unit blocks +TRUE +TRUE Expected +'#---------------------WL6372_VAR_2_07----------------------#' +# create 1 table and insert 3 rows each +DROP TABLE IF EXISTS tab1; +=============== +create table & Index +=============== +CREATE TABLE tab1 (col_1 text(10)) +ENGINE=INNODB ; +=============== +Load the data +=============== +SET @col_1 = repeat('a', 10); +INSERT INTO tab1 +VALUES (@col_1); +INSERT INTO tab1 +VALUES (@col_1); +INSERT INTO tab1 +VALUES (@col_1); +commit; +set @@GLOBAL.query_cache_size=DEFAULT; +select 1 from tab1 limit 1; +1 +1 +1 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_hits'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_inserts'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached'; +variable_value +19 +17 Expected +select 1 from tab1 limit 1; +1 +1 +1 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_hits'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_inserts'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached'; +variable_value +24 +22 Expected +select 1 from tab1 limit 2; +1 +1 +1 +1 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_hits'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_inserts'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached'; +variable_value +29 +27 Expected +# Restart server with query_cache_type ON +select 1 from tab1 limit 1; +1 +1 +1 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_hits'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_inserts'; +variable_value +1 +1 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache'; +variable_value +1 +1 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached'; +variable_value +10 +8 Expected +select 1 from tab1 limit 2; +1 +1 +1 +1 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_hits'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_inserts'; +variable_value +2 +2 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache'; +variable_value +2 +2 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached'; +variable_value +14 +12 Expected +select 1 from tab1 limit 1; +1 +1 +1 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_hits'; +variable_value +1 +1 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_inserts'; +variable_value +2 +2 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache'; +variable_value +2 +2 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached'; +variable_value +18 +16 Expected +# opening another client session +select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached'; +variable_value +19 +17 Expected +#cleanup +DROP TABLE IF EXISTS tab1; diff --git a/mysql-test/main/query_cache_type_functionality.result b/mysql-test/main/query_cache_type_functionality.result new file mode 100644 index 00000000000..134d8c3a066 --- /dev/null +++ b/mysql-test/main/query_cache_type_functionality.result @@ -0,0 +1,250 @@ +'#________________________VAR_03_query_cache_type__________________#' +echo '##' +--echo '#---------------------WL6372_VAR_3_01----------------------#' +#################################################################### +# Checking default value # +#################################################################### +SELECT COUNT(@@GLOBAL.query_cache_type) +1 Expected +SELECT @@GLOBAL.query_cache_type; +@@GLOBAL.query_cache_type +OFF +OFF Expected +'#---------------------WL6372_VAR_3_02----------------------#' +# Restart server with query_cache_type 1; +SELECT @@GLOBAL.query_cache_type; +@@GLOBAL.query_cache_type +ON +ON Expected +SET @@GLOBAL.query_cache_type=DEFAULT; +SELECT @@GLOBAL.query_cache_type; +@@GLOBAL.query_cache_type +OFF +OFF Expected +'#---------------------WL6372_VAR_3_03----------------------#' +SET @@local.query_cache_type=1; +SELECT @@Local.query_cache_type; +@@Local.query_cache_type +ON +ON Expected +SET @@session.query_cache_type=1; +SELECT @@Session.query_cache_type; +@@Session.query_cache_type +ON +ON Expected +SET @@GLOBAL.query_cache_type=1; +SELECT @@GLOBAL.query_cache_type; +@@GLOBAL.query_cache_type +ON +ON Expected +SET @@GLOBAL.query_cache_type=DEFAULT; +SELECT @@GLOBAL.query_cache_type; +@@GLOBAL.query_cache_type +OFF +OFF Expected +SET @@Session.query_cache_type=DEFAULT; +SELECT @@Session.query_cache_type; +@@Session.query_cache_type +OFF +OFF Expected +SET @@Local.query_cache_type=DEFAULT; +SELECT @@Local.query_cache_type; +@@Local.query_cache_type +OFF +OFF Expected +'#---------------------WL6372_VAR_3_04----------------------#' +SELECT @@GLOBAL.query_cache_type = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='query_cache_type'; +@@GLOBAL.query_cache_type = VARIABLE_VALUE +1 +1 Expected +SELECT COUNT(@@GLOBAL.query_cache_type); +COUNT(@@GLOBAL.query_cache_type) +1 +1 Expected +SELECT COUNT(VARIABLE_VALUE) +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='query_cache_type'; +COUNT(VARIABLE_VALUE) +1 +1 Expected +'#---------------------WL6372_VAR_3_05----------------------#' +SELECT @@query_cache_type = @@GLOBAL.query_cache_type; +@@query_cache_type = @@GLOBAL.query_cache_type +1 +1 Expected +SELECT @@query_cache_type = @@Session.query_cache_type; +@@query_cache_type = @@Session.query_cache_type +1 +1 Expected +SELECT COUNT(@@local.query_cache_type); +COUNT(@@local.query_cache_type) +1 +1 Expected +SELECT COUNT(@@SESSION.query_cache_type); +COUNT(@@SESSION.query_cache_type) +1 +1 Expected +SELECT COUNT(@@GLOBAL.query_cache_type); +COUNT(@@GLOBAL.query_cache_type) +1 +1 Expected +SELECT query_cache_type = @@SESSION.query_cache_type; +ERROR 42S22: Unknown column 'query_cache_type' in 'field list' +Expected error 'Unknown column query_cache_type in field list' +'#---------------------WL6372_VAR_3_06----------------------#' +Check the size of the vardir +The output size is in unit blocks +TRUE +TRUE Expected +'#---------------------WL6372_VAR_3_07----------------------#' +# create 1 table and insert 3 rows each +DROP TABLE IF EXISTS tab1; +=============== +create table & Index +=============== +CREATE TABLE tab1 (col_1 text(10)) +ENGINE=INNODB ; +=============== +Load the data +=============== +SET @col_1 = repeat('a', 10); +INSERT INTO tab1 +VALUES (@col_1); +INSERT INTO tab1 +VALUES (@col_1); +INSERT INTO tab1 +VALUES (@col_1); +commit; +set @@GLOBAL.query_cache_type=DEFAULT; +select 1 from tab1 limit 1; +1 +1 +1 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_hits'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_inserts'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached'; +variable_value +27 +25 Expected +select 1 from tab1 limit 1; +1 +1 +1 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_hits'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_inserts'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached'; +variable_value +32 +30 Expected +select 1 from tab1 limit 2; +1 +1 +1 +1 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_hits'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_inserts'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached'; +variable_value +37 +35 Expected +# Restart server with query_cache_type ON +select 1 from tab1 limit 1; +1 +1 +1 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_hits'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_inserts'; +variable_value +1 +1 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache'; +variable_value +1 +1 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached'; +variable_value +10 +8 Expected +select 1 from tab1 limit 2; +1 +1 +1 +1 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_hits'; +variable_value +0 +0 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_inserts'; +variable_value +2 +2 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache'; +variable_value +2 +2 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached'; +variable_value +14 +12 Expected +select 1 from tab1 limit 1; +1 +1 +1 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_hits'; +variable_value +1 +1 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_inserts'; +variable_value +2 +2 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_queries_in_cache'; +variable_value +2 +2 Expected +select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached'; +variable_value +18 +16 Expected +# opening another client session +select variable_value from information_schema.global_status where variable_name ='Qcache_not_cached'; +variable_value +19 +17 Expected +#cleanup +DROP TABLE IF EXISTS tab1; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index af908297d65..fec4f332978 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2902,6 +2902,55 @@ sub mysql_server_wait { $warn_seconds); } +sub have_wsrep() { + my $wsrep_on= $mysqld_variables{'wsrep-on'}; + return defined $wsrep_on +} + +sub wsrep_is_bootstrap_server($) { + my $mysqld= shift; + return $mysqld->if_exist('wsrep_cluster_address') && + ($mysqld->value('wsrep_cluster_address') eq "gcomm://" || + $mysqld->value('wsrep_cluster_address') eq "'gcomm://'"); +} + +sub check_wsrep_support() { + if (have_wsrep()) + { + mtr_report(" - binaries built with wsrep patch"); + + # ADD scripts to $PATH to that wsrep_sst_* can be found + my ($path) = grep { -f "$_/wsrep_sst_rsync"; } "$::bindir/scripts", $::path_client_bindir; + mtr_error("No SST scripts") unless $path; + $ENV{PATH}="$path:$ENV{PATH}"; + + # Check whether WSREP_PROVIDER environment variable is set. + if (defined $ENV{'WSREP_PROVIDER'}) { + if ((mtr_file_exists($ENV{'WSREP_PROVIDER'}) eq "") && + ($ENV{'WSREP_PROVIDER'} ne "none")) { + mtr_error("WSREP_PROVIDER env set to an invalid path"); + } + # WSREP_PROVIDER is valid; set to a valid path or "none"). + mtr_verbose("WSREP_PROVIDER env set to $ENV{'WSREP_PROVIDER'}"); + } else { + # WSREP_PROVIDER env not defined. Lets try to locate the wsrep provider + # library. + my $file_wsrep_provider= + mtr_file_exists("/usr/lib/galera/libgalera_smm.so", + "/usr/lib64/galera/libgalera_smm.so"); + + if ($file_wsrep_provider ne "") { + # wsrep provider library found ! + mtr_verbose("wsrep provider library found : $file_wsrep_provider"); + $ENV{'WSREP_PROVIDER'}= $file_wsrep_provider; + } else { + mtr_verbose("Could not find wsrep provider library, setting it to 'none'"); + $ENV{'WSREP_PROVIDER'}= "none"; + } + } + } +} + sub create_config_file_for_extern { my %opts= ( @@ -3365,6 +3414,60 @@ sub run_query { } +sub run_query_output { + my ($mysqld, $query, $outfile)= @_; + + my $args; + mtr_init_args(\$args); + mtr_add_arg($args, "--defaults-file=%s", $path_config_file); + mtr_add_arg($args, "--defaults-group-suffix=%s", $mysqld->after('mysqld')); + + mtr_add_arg($args, "--silent"); + mtr_add_arg($args, "--execute=%s", $query); + + my $res= My::SafeProcess->run + ( + name => "run_query_output -> ".$mysqld->name(), + path => $exe_mysql, + args => \$args, + output => $outfile, + error => $outfile + ); + + return $res +} + + +sub wait_wsrep_ready($$) { + my ($tinfo, $mysqld)= @_; + + my $sleeptime= 100; # Milliseconds + my $loops= ($opt_start_timeout * 1000) / $sleeptime; + + my $name= $mysqld->name(); + my $outfile= "$opt_vardir/tmp/$name.wsrep_ready"; + my $query= "SET SESSION wsrep_sync_wait = 0; + SELECT VARIABLE_VALUE + FROM INFORMATION_SCHEMA.GLOBAL_STATUS + WHERE VARIABLE_NAME = 'wsrep_ready'"; + + for (my $loop= 1; $loop <= $loops; $loop++) + { + if (run_query_output($mysqld, $query, $outfile) == 0 && + mtr_grab_file($outfile) =~ /^ON/) + { + unlink($outfile); + return 1; + } + + mtr_milli_sleep($sleeptime); + } + + $tinfo->{logfile}= "WSREP did not transition to state READY"; + return 0; +} + + sub do_before_run_mysqltest($) { my $tinfo= shift; @@ -5410,6 +5513,21 @@ sub start_servers($) { for (all_servers()) { $_->{START}->($_, $tinfo) if $_->{START}; + # If wsrep is on, we need to wait until the first + # server starts and bootstraps the cluster before + # starting other servers. The bootsrap server in the + # configuration should always be the first which has + # wsrep_on=ON and should be tagged with "#wsrep-new-cluster". + # option + if (have_wsrep() && (defined $_->option("#wsrep-new-cluster") || + wsrep_is_bootstrap_server($_))) + { + mtr_debug("Waiting the first wsrep server to start"); + if ($_->{WAIT}->($_) && !wait_wsrep_ready($tinfo, $_)) + { + return 1; + } + } } for (all_servers()) { @@ -5418,7 +5536,13 @@ sub start_servers($) { $tinfo->{comment}= "Failed to start ".$_->name() . "\n"; return 1; } + + if (have_wsrep() && !wait_wsrep_ready($tinfo, $_)) + { + return 1; + } } + return 0; } diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 322eff3506f..0dca1db66a7 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -9,7 +9,7 @@ # Do not use any TAB characters for whitespace. # ############################################################################## - +MW-360 : needs rewrite to be MariaDB gtid compatible galera_flush : MariaDB does not have global.thread_statistics galera_account_management : MariaDB 10.0 does not support ALTER USER galera_binlog_rows_query_log_events: MariaDB does not support binlog_rows_query_log_events diff --git a/mysql-test/suite/galera/galera_2nodes.cnf b/mysql-test/suite/galera/galera_2nodes.cnf index b24f3603894..68e4759ee9b 100644 --- a/mysql-test/suite/galera/galera_2nodes.cnf +++ b/mysql-test/suite/galera/galera_2nodes.cnf @@ -2,6 +2,7 @@ !include include/default_mysqld.cnf [mysqld] +loose-innodb wsrep-on=1 binlog-format=row innodb-autoinc-lock-mode=2 @@ -10,20 +11,34 @@ wsrep-provider=@ENV.WSREP_PROVIDER wsrep_node_address=127.0.0.1 # enforce read-committed characteristics across the cluster wsrep-sync-wait=15 - +# lock schedule alg appears to be VATS by default, and it is not +# yet compatible with galera +innodb_lock_schedule_algorithm=FCFS [mysqld.1] +loose-innodb #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port +#wsrep-new-cluster wsrep-cluster-address=gcomm:// wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M' wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' +# enforce read-committed characteristics across the cluster +wsrep_causal_reads=ON +wsrep_sync_wait = 15 +# lock schedule alg appears to be VATS by default, and it is not +# yet compatible with galera +innodb_lock_schedule_algorithm=FCFS + [mysqld.2] +loose-innodb +# debug=d:t:i:o,/tmp/mysqld.2.trace #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port + wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S' @@ -34,8 +49,14 @@ wsrep_sync_wait = 15 wsrep_node_address=127.0.0.1 wsrep_sst_receive_address=127.0.0.2:@mysqld.2.#sst_port wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port -wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' +wsrep_sst_receive_address='127.0.0.2:@mysqld.2.#sst_port' +# enforce read-committed characteristics across the cluster +wsrep_causal_reads=ON +wsrep_sync_wait = 15 +# lock schedule alg appears to be VATS by default, and it is not +# yet compatible with galera +innodb_lock_schedule_algorithm=FCFS [ENV] NODE_MYPORT_1= @mysqld.1.port diff --git a/mysql-test/suite/galera/galera_2nodes_as_master.cnf b/mysql-test/suite/galera/galera_2nodes_as_master.cnf index 33bfc475721..f856b58ab14 100644 --- a/mysql-test/suite/galera/galera_2nodes_as_master.cnf +++ b/mysql-test/suite/galera/galera_2nodes_as_master.cnf @@ -11,6 +11,9 @@ log-bin=mysqld-bin binlog-format=row innodb-autoinc-lock-mode=2 default-storage-engine=innodb +# lock schedule alg appears to be VATS by default, and it is not +# yet compatible with galera +innodb_lock_schedule_algorithm=FCFS [mysqld.1] #galera_port=@OPT.port @@ -30,6 +33,9 @@ wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port # enforce read-committed characteristics across the cluster wsrep-causal-reads=ON wsrep-sync-wait=15 +# lock schedule alg appears to be VATS by default, and it is not +# yet compatible with galera +innodb_lock_schedule_algorithm=FCFS [mysqld.2] #galera_port=@OPT.port @@ -49,9 +55,15 @@ wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port # enforce read-committed characteristics across the cluster wsrep-causal-reads=ON wsrep-sync-wait=15 +# lock schedule alg appears to be VATS by default, and it is not +# yet compatible with galera +innodb_lock_schedule_algorithm=FCFS [mysqld.3] server-id=3 +# lock schedule alg appears to be VATS by default, and it is not +# yet compatible with galera +innodb_lock_schedule_algorithm=FCFS [ENV] NODE_MYPORT_1= @mysqld.1.port diff --git a/mysql-test/suite/galera/galera_2nodes_as_slave.cnf b/mysql-test/suite/galera/galera_2nodes_as_slave.cnf index 4d9e39d2aae..b432c9db7d3 100644 --- a/mysql-test/suite/galera/galera_2nodes_as_slave.cnf +++ b/mysql-test/suite/galera/galera_2nodes_as_slave.cnf @@ -9,17 +9,14 @@ binlog-format=row [mysqld.1] -log-bin -server-id=1 - -[mysqld.2] #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port wsrep-on=1 -log-bin +log-bin=master-bin +log-bin-index=master-bin log-slave-updates innodb-autoinc-lock-mode=2 @@ -27,38 +24,54 @@ default-storage-engine=innodb wsrep-provider=@ENV.WSREP_PROVIDER wsrep_node_address=127.0.0.1 wsrep-cluster-address=gcomm:// -wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=10M' -wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port -wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' +wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=10M' +wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port +wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' # enforce read-committed characteristics across the cluster wsrep-causal-reads=ON wsrep-sync-wait=15 -server-id=2 +server-id=1 +# lock schedule alg appears to be VATS by default, and it is not +# yet compatible with galera +innodb_lock_schedule_algorithm=FCFS -[mysqld.3] +[mysqld.2] #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port wsrep-on=1 -log-bin +log-bin=master-bin +log-bin-index=master-bin log-slave-updates innodb-autoinc-lock-mode=2 default-storage-engine=innodb wsrep-provider=@ENV.WSREP_PROVIDER wsrep_node_address=127.0.0.1 -wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.2.#galera_port' -wsrep_provider_options='base_port=@mysqld.3.#galera_port;gcache.size=10M' -wsrep_node_incoming_address=127.0.0.1:@mysqld.3.port -wsrep_sst_receive_address='127.0.0.1:@mysqld.3.#sst_port' +wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' +wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=10M' +wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port +wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' # enforce read-committed characteristics across the cluster wsrep-causal-reads=ON wsrep-sync-wait=15 +server-id=2 +# lock schedule alg appears to be VATS by default, and it is not +# yet compatible with galera +innodb_lock_schedule_algorithm=FCFS + +[mysqld.1] +log-bin=master-bin +log-bin-index=master-bin server-id=3 +# lock schedule alg appears to be VATS by default, and it is not +# yet compatible with galera +innodb_lock_schedule_algorithm=FCFS + [ENV] NODE_MYPORT_1= @mysqld.1.port @@ -70,8 +83,8 @@ NODE_MYSOCK_2= @mysqld.2.socket NODE_MYPORT_3= @mysqld.3.port NODE_MYSOCK_3= @mysqld.3.socket +NODE_GALERAPORT_1= @mysqld.1.#galera_port NODE_GALERAPORT_2= @mysqld.2.#galera_port -NODE_GALERAPORT_3= @mysqld.3.#galera_port +NODE_SSTPORT_1= @mysqld.1.#sst_port NODE_SSTPORT_2= @mysqld.2.#sst_port -NODE_SSTPORT_3= @mysqld.3.#sst_port diff --git a/mysql-test/suite/galera/galera_3nodes_as_slave.cnf b/mysql-test/suite/galera/galera_3nodes_as_slave.cnf index ac1ca34e242..26640374be9 100644 --- a/mysql-test/suite/galera/galera_3nodes_as_slave.cnf +++ b/mysql-test/suite/galera/galera_3nodes_as_slave.cnf @@ -8,15 +8,15 @@ [mysqld] log-bin binlog-format=row +# lock schedule alg appears to be VATS by default, and it is not +# yet compatible with galera +innodb_lock_schedule_algorithm=FCFS [mysqld.1] -server-id=1 - -[mysqld.2] #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port - +wsrep-on=1 log-slave-updates innodb-autoinc-lock-mode=2 @@ -24,19 +24,23 @@ default-storage-engine=innodb wsrep-provider=@ENV.WSREP_PROVIDER wsrep_node_address=127.0.0.1 wsrep-cluster-address=gcomm:// -wsrep_provider_options='base_port=@mysqld.2.#galera_port;evs.install_timeout = PT15S;evs.max_install_timeouts=1;gcache.size=10M' -wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port -wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' +wsrep_provider_options='base_port=@mysqld.1.#galera_port;evs.install_timeout = PT15S;evs.max_install_timeouts=1;gcache.size=10M' +wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port +wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' # enforce read-committed characteristics across the cluster wsrep-causal-reads=ON wsrep-sync-wait=15 -server-id=2 +server-id=1 +# lock schedule alg appears to be VATS by default, and it is not +# yet compatible with galera +innodb_lock_schedule_algorithm=FCFS -[mysqld.3] +[mysqld.2] #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port +wsrep-on=1 log-slave-updates @@ -44,20 +48,24 @@ innodb-autoinc-lock-mode=2 default-storage-engine=innodb wsrep-provider=@ENV.WSREP_PROVIDER wsrep_node_address=127.0.0.1 -wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.2.#galera_port' -wsrep_provider_options='base_port=@mysqld.3.#galera_port;evs.install_timeout=PT15S;evs.max_install_timeouts=1;gcache.size=10M' -wsrep_node_incoming_address=127.0.0.1:@mysqld.3.port -wsrep_sst_receive_address='127.0.0.1:@mysqld.3.#sst_port' +wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' +wsrep_provider_options='base_port=@mysqld.2.#galera_port;evs.install_timeout=PT15S;evs.max_install_timeouts=1;gcache.size=10M' +wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port +wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' # enforce read-committed characteristics across the cluster wsrep-causal-reads=ON wsrep-sync-wait=15 -server-id=3 +server-id=2 +# lock schedule alg appears to be VATS by default, and it is not +# yet compatible with galera +innodb_lock_schedule_algorithm=FCFS -[mysqld.4] +[mysqld.3] #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port +wsrep-on=1 log-slave-updates @@ -65,15 +73,24 @@ innodb-autoinc-lock-mode=2 default-storage-engine=innodb wsrep-provider=@ENV.WSREP_PROVIDER wsrep_node_address=127.0.0.1 -wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.2.#galera_port' -wsrep_provider_options='base_port=@mysqld.4.#galera_port;evs.install_timeout=PT15S;evs.max_install_timeouts=1;gcache.size=10M' -wsrep_node_incoming_address=127.0.0.1:@mysqld.4.port -wsrep_sst_receive_address='127.0.0.1:@mysqld.4.#sst_port' +wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' +wsrep_provider_options='base_port=@mysqld.3.#galera_port;evs.install_timeout=PT15S;evs.max_install_timeouts=1;gcache.size=10M' +wsrep_node_incoming_address=127.0.0.1:@mysqld.3.port +wsrep_sst_receive_address='127.0.0.1:@mysqld.3.#sst_port' # enforce read-committed characteristics across the cluster wsrep-causal-reads=ON wsrep-sync-wait=15 +server-id=3 +# lock schedule alg appears to be VATS by default, and it is not +# yet compatible with galera +innodb_lock_schedule_algorithm=FCFS + +[mysqld.4] server-id=4 +# lock schedule alg appears to be VATS by default, and it is not +# yet compatible with galera +innodb_lock_schedule_algorithm=FCFS [ENV] NODE_MYPORT_1= @mysqld.1.port @@ -88,10 +105,10 @@ NODE_MYSOCK_3= @mysqld.3.socket NODE_MYPORT_4= @mysqld.4.port NODE_MYSOCK_4= @mysqld.4.socket +NODE_GALERAPORT_1= @mysqld.1.#galera_port NODE_GALERAPORT_2= @mysqld.2.#galera_port NODE_GALERAPORT_3= @mysqld.3.#galera_port -NODE_GALERAPORT_4= @mysqld.4.#galera_port +NODE_SSTPORT_1= @mysqld.1.#sst_port NODE_SSTPORT_2= @mysqld.2.#sst_port NODE_SSTPORT_3= @mysqld.3.#sst_port -NODE_SSTPORT_4= @mysqld.4.#sst_port diff --git a/mysql-test/suite/galera/galera_4nodes.cnf b/mysql-test/suite/galera/galera_4nodes.cnf index 1c195afd54b..2d348c0c2ed 100644 --- a/mysql-test/suite/galera/galera_4nodes.cnf +++ b/mysql-test/suite/galera/galera_4nodes.cnf @@ -11,6 +11,9 @@ wsrep_node_address=127.0.0.1 # enforce read-committed characteristics across the cluster wsrep-causal-reads=ON wsrep-sync-wait=15 +# lock schedule alg appears to be VATS by default, and it is not +# yet compatible with galera +innodb_lock_schedule_algorithm=FCFS [mysqld.1] #galera_port=@OPT.port @@ -20,6 +23,9 @@ wsrep-cluster-address=gcomm:// wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=10M' wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' +# lock schedule alg appears to be VATS by default, and it is not +# yet compatible with galera +innodb_lock_schedule_algorithm=FCFS [mysqld.2] #galera_port=@OPT.port @@ -29,6 +35,9 @@ wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=10M' wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' +# lock schedule alg appears to be VATS by default, and it is not +# yet compatible with galera +innodb_lock_schedule_algorithm=FCFS [mysqld.3] @@ -39,6 +48,9 @@ wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' wsrep_provider_options='base_port=@mysqld.3.#galera_port;gcache.size=10M' wsrep_node_incoming_address=127.0.0.1:@mysqld.3.port wsrep_sst_receive_address='127.0.0.1:@mysqld.3.#sst_port' +# lock schedule alg appears to be VATS by default, and it is not +# yet compatible with galera +innodb_lock_schedule_algorithm=FCFS [mysqld.4] @@ -49,6 +61,9 @@ wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' wsrep_provider_options='base_port=@mysqld.4.#galera_port;gcache.size=10M' wsrep_node_incoming_address=127.0.0.1:@mysqld.4.port wsrep_sst_receive_address='127.0.0.1:@mysqld.4.#sst_port' +# lock schedule alg appears to be VATS by default, and it is not +# yet compatible with galera +innodb_lock_schedule_algorithm=FCFS [ENV] NODE_MYPORT_1= @mysqld.1.port diff --git a/mysql-test/suite/galera/include/galera_load_provider.inc b/mysql-test/suite/galera/include/galera_load_provider.inc index aeab7e6ea19..0f843597d9c 100644 --- a/mysql-test/suite/galera/include/galera_load_provider.inc +++ b/mysql-test/suite/galera/include/galera_load_provider.inc @@ -2,7 +2,75 @@ --disable_query_log --eval SET GLOBAL wsrep_provider = '$wsrep_provider_orig'; + +# +# count occurences of successful node starts in error log +# +perl; + use strict; + my $test_log=$ENV{'LOG_FILE'} or die "LOG_FILE not set"; + my $test_log_copy=$test_log . '.copy'; + if (-e $test_log_copy) { + unlink $test_log_copy; + } + +EOF +--copy_file $LOG_FILE $LOG_FILE.copy + +# +# now join to the cluster +# --eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_orig'; + +--enable_query_log + +# +# Cluster address change above, will launch SST/IST +# if mysqldump ST has been configured, mysqld will close all +# client connections, and it will be hard for us to poll for +# cluster status during SST process, therefore wait_until_connected_again.inc +# and wait_until_ready.inc may fail in this phase +# To workaround this, we do first lazy polling here just to see when +# client connections will be possible, and after that check for node readyness +# +--disable_result_log +--disable_query_log + +--error 0,1 +perl; + use strict; + my $logfile = $ENV{'LOG_FILE'} or die ("no error log file set"); + + my $counter = 1000; + #my $found = false + + while ($counter > 0) { + + open(FILE, "$logfile") or die("Unable to open $logfile : $!\n"); + my $new_sync_count = () = grep(/Synchronized with group/g,<FILE>); + close(FILE); + + open(FILEN, "$logfile.copy") or die("Unable to open $logfile.copy : $!\n"); + my $old_sync_count = () = grep(/Synchronized with group/g,<FILEN>); + close(FILEN); + + if ($new_sync_count > $old_sync_count ) { + exit(0); + } + $counter--; + sleep(5); + } + exit(1); +EOF +if ($errno) +{ +--echo "SST failed $errno" +} + +--remove_file $LOG_FILE.copy + --enable_query_log +--enable_result_log +#--eval SET GLOBAL log_error = $log_error_; --source include/galera_wait_ready.inc diff --git a/mysql-test/suite/galera/include/galera_resume.inc b/mysql-test/suite/galera/include/galera_resume.inc index 232cb46479e..af8f2b956fd 100644 --- a/mysql-test/suite/galera/include/galera_resume.inc +++ b/mysql-test/suite/galera/include/galera_resume.inc @@ -3,7 +3,7 @@ my $pid_filename = $ENV{'_SUSPEND_NODE_PIDFILE'}; my $mysqld_pid = `cat $pid_filename`; chomp($mysqld_pid); - system("kill -18 $mysqld_pid"); + system("kill -SIGCONT $mysqld_pid"); exit(0); EOF diff --git a/mysql-test/suite/galera/include/galera_sst_restore.inc b/mysql-test/suite/galera/include/galera_sst_restore.inc index 7c9a08090ad..83d07f086d1 100644 --- a/mysql-test/suite/galera/include/galera_sst_restore.inc +++ b/mysql-test/suite/galera/include/galera_sst_restore.inc @@ -20,7 +20,7 @@ CALL mtr.add_suppression("Can't open and lock time zone table"); CALL mtr.add_suppression("Can't open and lock privilege tables"); CALL mtr.add_suppression("Info table is not ready to be used"); CALL mtr.add_suppression("Native table .* has the wrong structure"); - +CALL mtr.add_suppression("Table \'mysql.gtid_slave_pos\' doesn\'t exist"); --disable_query_log --eval SET GLOBAL wsrep_sst_method = '$wsrep_sst_method_orig'; --eval SET GLOBAL wsrep_sst_receive_address = '$wsrep_sst_receive_address_orig'; diff --git a/mysql-test/suite/galera/include/galera_st_clean_slave.inc b/mysql-test/suite/galera/include/galera_st_clean_slave.inc index 3a49f4f6ad2..52044775186 100644 --- a/mysql-test/suite/galera/include/galera_st_clean_slave.inc +++ b/mysql-test/suite/galera/include/galera_st_clean_slave.inc @@ -34,6 +34,7 @@ COMMIT; --remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/performance_schema --remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/test --remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/mysql +--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/wsrep_schema --remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data SET AUTOCOMMIT=OFF; diff --git a/mysql-test/suite/galera/include/galera_st_disconnect_slave.inc b/mysql-test/suite/galera/include/galera_st_disconnect_slave.inc index c8869746bd1..d6d7552f7b6 100644 --- a/mysql-test/suite/galera/include/galera_st_disconnect_slave.inc +++ b/mysql-test/suite/galera/include/galera_st_disconnect_slave.inc @@ -55,6 +55,14 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); --connection node_2 --source suite/galera/include/galera_load_provider.inc +# +# client connections were killed by provider load, so have to re-open here +# +--disconnect node_2 +--connect node_2, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2 +--enable_reconnect + --let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' --source include/wait_condition.inc diff --git a/mysql-test/suite/galera/include/galera_unload_provider.inc b/mysql-test/suite/galera/include/galera_unload_provider.inc index edc7eb31e0e..cd841f51fbc 100644 --- a/mysql-test/suite/galera/include/galera_unload_provider.inc +++ b/mysql-test/suite/galera/include/galera_unload_provider.inc @@ -3,5 +3,13 @@ --let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address` --let $wsrep_provider_orig = `SELECT @@wsrep_provider` --let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options` +--let $wsrep_error_log_orig = `SELECT @@log_error` +if(!$wsrep_log_error_orig) +{ + # MySQL Server on windows is started with --console and thus + # does not know the location of its .err log, use default location + let $wsrep_log_error_orig = $MYSQLTEST_VARDIR/log/mysqld.2.err; +} +--let LOG_FILE= $wsrep_log_error_orig SET GLOBAL wsrep_provider = 'none'; diff --git a/mysql-test/suite/galera/r/GAL-382.result b/mysql-test/suite/galera/r/GAL-382.result index fb7c229bd56..137efe4efba 100644 --- a/mysql-test/suite/galera/r/GAL-382.result +++ b/mysql-test/suite/galera/r/GAL-382.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; create table t1 (i int, j int, k int, primary key pk(i)) engine=innodb; insert into t1 values (1, 1, 1), (2, 2, 2), (3, 3, 3); diff --git a/mysql-test/suite/galera/r/GAL-401.result b/mysql-test/suite/galera/r/GAL-401.result index 3b55b7589b7..3dfc32ffb8c 100644 --- a/mysql-test/suite/galera/r/GAL-401.result +++ b/mysql-test/suite/galera/r/GAL-401.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; connection node_2; SET @@global.wsrep_desync = 1; diff --git a/mysql-test/suite/galera/r/GCF-1081.result b/mysql-test/suite/galera/r/GCF-1081.result new file mode 100644 index 00000000000..ede512ec6b1 --- /dev/null +++ b/mysql-test/suite/galera/r/GCF-1081.result @@ -0,0 +1,47 @@ +connection node_2; +connection node_1; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 0), (3, 0); +CREATE PROCEDURE proc_update () +BEGIN +UPDATE t1 SET f2 = 1 where f1 > 0; +END| +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync'; +connection node_1; +CALL proc_update ();; +connection node_1a; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +connection node_1a; +SET GLOBAL DEBUG = 'd,sync.wsrep_before_BF_victim_unlock'; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +connection node_2; +INSERT INTO t1 VALUES (2, 2);; +connection node_1a; +SET SESSION DEBUG_SYNC = 'now WAIT_FOR sync.wsrep_before_BF_victim_unlock_reached'; +SET GLOBAL DEBUG = ''; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +connection node_1a; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync'; +connection node_2; +SELECT * FROM t1; +f1 f2 +1 1 +2 2 +3 1 +connection node_1; +SELECT * FROM t1; +f1 f2 +1 1 +2 2 +3 1 +wsrep_local_replays +1 +DROP PROCEDURE proc_update; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/GCF-939.result b/mysql-test/suite/galera/r/GCF-939.result new file mode 100644 index 00000000000..57b04efa529 --- /dev/null +++ b/mysql-test/suite/galera/r/GCF-939.result @@ -0,0 +1,12 @@ +connection node_2; +connection node_1; +connection node_1; +DROP TABLE t1; +ERROR 42S02: Unknown table 'test.t1' +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +GRA_.log +DROP TABLE t1; +CALL mtr.add_suppression("Ignoring error 'Unknown table 'test.t1'' on query"); +connection node_2; +CALL mtr.add_suppression("Error 'Unknown table 'test.t1'' on query"); diff --git a/mysql-test/suite/galera/r/MDEV-15443.result b/mysql-test/suite/galera/r/MDEV-15443.result index 618e5459878..21332b372e8 100644 --- a/mysql-test/suite/galera/r/MDEV-15443.result +++ b/mysql-test/suite/galera/r/MDEV-15443.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; diff --git a/mysql-test/suite/galera/r/MW-252.result b/mysql-test/suite/galera/r/MW-252.result index 795d3fff670..4d458802614 100644 --- a/mysql-test/suite/galera/r/MW-252.result +++ b/mysql-test/suite/galera/r/MW-252.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; FLUSH TABLES WITH READ LOCK; diff --git a/mysql-test/suite/galera/r/MW-258.result b/mysql-test/suite/galera/r/MW-258.result index 1c2a1744c98..22963557daf 100644 --- a/mysql-test/suite/galera/r/MW-258.result +++ b/mysql-test/suite/galera/r/MW-258.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (f1 INTEGER); LOCK TABLE t1 WRITE; diff --git a/mysql-test/suite/galera/r/MW-259.result b/mysql-test/suite/galera/r/MW-259.result index 5256a95c52c..9a0f2ccfa23 100644 --- a/mysql-test/suite/galera/r/MW-259.result +++ b/mysql-test/suite/galera/r/MW-259.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1; connection node_1; diff --git a/mysql-test/suite/galera/r/MW-284.result b/mysql-test/suite/galera/r/MW-284.result index 0f6c0be25fe..b95639c568a 100644 --- a/mysql-test/suite/galera/r/MW-284.result +++ b/mysql-test/suite/galera/r/MW-284.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; connection node_1; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; @@ -24,7 +26,9 @@ RESET SLAVE ALL; CALL mtr.add_suppression('failed registering on master'); CALL mtr.add_suppression('You need to use --log-bin to make --binlog-format work'); connection node_1; +set global wsrep_on=OFF; RESET MASTER; +set global wsrep_on=OFF; CALL mtr.add_suppression('WSREP: Last Applied Action message in non-primary configuration from member'); connection node_2; CALL mtr.add_suppression('WSREP: Last Applied Action message in non-primary configuration from member'); diff --git a/mysql-test/suite/galera/r/MW-285.result b/mysql-test/suite/galera/r/MW-285.result index 8c5a21fcbee..762f22d5d25 100644 --- a/mysql-test/suite/galera/r/MW-285.result +++ b/mysql-test/suite/galera/r/MW-285.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE parent1 ( id INT PRIMARY KEY, KEY (id) ) ENGINE=InnoDB; CREATE TABLE parent2 ( id INT PRIMARY KEY, KEY (id) ) ENGINE=InnoDB; CREATE TABLE child ( diff --git a/mysql-test/suite/galera/r/MW-292.result b/mysql-test/suite/galera/r/MW-292.result index 5b9214ace2a..81e5a316b63 100644 --- a/mysql-test/suite/galera/r/MW-292.result +++ b/mysql-test/suite/galera/r/MW-292.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE rand_table (f1 FLOAT); CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)); INSERT INTO t1 VALUES (1, 'a'); @@ -10,19 +12,28 @@ SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE; f1 f2 2 a connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; -SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_enter_sync'; -connection node_1; -COMMIT;; -connection node_1a; -SET SESSION wsrep_sync_wait = 0; -SET SESSION wsrep_on = 0; -SET SESSION wsrep_on = 1; +SET SESSION wsrep_sync_wait=0; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; connection node_2; UPDATE t1 SET f2 = 'c' WHERE f1 = 2; connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync'; +connection node_1; +COMMIT; connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'dbug='; -SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync'; connection node_1; SELECT TIMEDIFF(SYSDATE(), NOW()) < 2; TIMEDIFF(SYSDATE(), NOW()) < 2 diff --git a/mysql-test/suite/galera/r/MW-309.result b/mysql-test/suite/galera/r/MW-309.result index 3dd49a041ee..0169b56e3e1 100644 --- a/mysql-test/suite/galera/r/MW-309.result +++ b/mysql-test/suite/galera/r/MW-309.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); INSERT INTO t1 SELECT * FROM t1; diff --git a/mysql-test/suite/galera/r/MW-313.result b/mysql-test/suite/galera/r/MW-313.result index dc605ffc370..909caf77f1d 100644 --- a/mysql-test/suite/galera/r/MW-313.result +++ b/mysql-test/suite/galera/r/MW-313.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); INSERT INTO t1 SELECT * FROM t1; diff --git a/mysql-test/suite/galera/r/MW-328A.result b/mysql-test/suite/galera/r/MW-328A.result index db0301b6bf2..266c5637b9b 100644 --- a/mysql-test/suite/galera/r/MW-328A.result +++ b/mysql-test/suite/galera/r/MW-328A.result @@ -14,10 +14,6 @@ connection node_1X; CALL proc_update();; connection node_2; SET SESSION wsrep_retry_autocommit = 0; -have_successes -1 -have_deadlocks -1 connection node_1; connection node_1X; Got one of the listed errors @@ -25,3 +21,17 @@ connection node_1; DROP PROCEDURE proc_update; DROP TABLE t1, t2; CALL mtr.add_suppression("conflict state 3 after post commit"); +CREATE TABLE t1 (i int primary key, j int) engine=innodb; +INSERT INTO t1 values (1,0); +BEGIN; +UPDATE t1 SET j=1 WHERE i=1; +UPDATE t1 SET j=2 WHERE i=1; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM t1; +i j +1 2 +SELECT * FROM t1; +i j +1 2 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/MW-328B.result b/mysql-test/suite/galera/r/MW-328B.result index e898e315ca8..d29c3a50f3d 100644 --- a/mysql-test/suite/galera/r/MW-328B.result +++ b/mysql-test/suite/galera/r/MW-328B.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 CHAR(20) DEFAULT 'abc') ENGINE=InnoDB; INSERT INTO t1 (f1) VALUES (1); CREATE TABLE t2 (f1 CHAR(20)) ENGINE=InnoDB; diff --git a/mysql-test/suite/galera/r/MW-328C.result b/mysql-test/suite/galera/r/MW-328C.result index d8e164e7b4a..748f9420764 100644 --- a/mysql-test/suite/galera/r/MW-328C.result +++ b/mysql-test/suite/galera/r/MW-328C.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 CHAR(20) DEFAULT 'abc') ENGINE=InnoDB; INSERT INTO t1 (f1) VALUES (1); CREATE TABLE t2 (f1 CHAR(20)) ENGINE=InnoDB; diff --git a/mysql-test/suite/galera/r/MW-328D.result b/mysql-test/suite/galera/r/MW-328D.result index 6562136ec27..43e1cefe08f 100644 --- a/mysql-test/suite/galera/r/MW-328D.result +++ b/mysql-test/suite/galera/r/MW-328D.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (i INT) ENGINE = InnoDB; INSERT INTO t1 (i) VALUES(1); CREATE TABLE t2 (i INT) ENGINE = InnoDB; diff --git a/mysql-test/suite/galera/r/MW-328E.result b/mysql-test/suite/galera/r/MW-328E.result index 89654ec066a..729fdea1a63 100644 --- a/mysql-test/suite/galera/r/MW-328E.result +++ b/mysql-test/suite/galera/r/MW-328E.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; create table t1 (i int primary key, j int) engine=innodb; create table t2 (i int primary key, j int) engine=innodb; insert into t1 values (1,0); diff --git a/mysql-test/suite/galera/r/MW-329.result b/mysql-test/suite/galera/r/MW-329.result index a3cb7277a9c..334ff9f80fb 100644 --- a/mysql-test/suite/galera/r/MW-329.result +++ b/mysql-test/suite/galera/r/MW-329.result @@ -1,10 +1,6 @@ CALL mtr.add_suppression("WSREP: .*conflict state . after post commit .*"); CREATE TABLE t1 (f1 INTEGER, f2 CHAR(20) DEFAULT 'abc') ENGINE=InnoDB; INSERT INTO t1 (f1) VALUES (1),(65535); -FLUSH STATUS; -SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'; -VARIABLE_VALUE = 0 -1 CREATE PROCEDURE proc_insert () BEGIN DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END; @@ -16,10 +12,7 @@ END| connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1; connection node_1b; CALL proc_insert();; -connection node_2; -CALL mtr.add_suppression("WSREP: Failed to report last committed .*"); -SELECT VARIABLE_VALUE > 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'; -VARIABLE_VALUE > 0 +wsrep_local_replays 1 connection node_1; connection node_1b; diff --git a/mysql-test/suite/galera/r/MW-336.result b/mysql-test/suite/galera/r/MW-336.result index 0bf8d9d3909..b1509da3856 100644 --- a/mysql-test/suite/galera/r/MW-336.result +++ b/mysql-test/suite/galera/r/MW-336.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; connection node_1; SET GLOBAL wsrep_slave_threads = 10; diff --git a/mysql-test/suite/galera/r/MW-357.result b/mysql-test/suite/galera/r/MW-357.result index 35855e21233..dc391be4dd3 100644 --- a/mysql-test/suite/galera/r/MW-357.result +++ b/mysql-test/suite/galera/r/MW-357.result @@ -1,4 +1,6 @@ connection node_2; +connection node_1; +connection node_2; SET GLOBAL wsrep_slave_threads = 0; Warnings: Warning 1292 Truncated incorrect wsrep_slave_threads value: '0' diff --git a/mysql-test/suite/galera/r/MW-360.result b/mysql-test/suite/galera/r/MW-360.result new file mode 100644 index 00000000000..f20d5be2135 --- /dev/null +++ b/mysql-test/suite/galera/r/MW-360.result @@ -0,0 +1,41 @@ +SET GLOBAL wsrep_on=OFF; +RESET MASTER; +SET GLOBAL wsrep_on=ON; +SET GLOBAL wsrep_on=OFF; +RESET MASTER; +SET GLOBAL wsrep_on=ON; +CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +DROP TABLE t1; +CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t2 VALUES (2); +DROP TABLE t1, t2; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +CREATE TEMPORARY TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t2 VALUES (2); +DROP TABLE t1, t2; +CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t2 VALUES (2); +CREATE TEMPORARY TABLE t3 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t3 VALUES (3); +DROP TABLE t1, t2, t3; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +CREATE TEMPORARY TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t2 VALUES (2); +CREATE TABLE t3 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t3 VALUES (3); +DROP TABLE t1, t2, t3; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (2); +DROP TABLE t1; +DROP TABLE t1; +gtid_executed_equal +1 diff --git a/mysql-test/suite/galera/r/MW-369.result b/mysql-test/suite/galera/r/MW-369.result index 516904d1b2a..4f36193fd59 100644 --- a/mysql-test/suite/galera/r/MW-369.result +++ b/mysql-test/suite/galera/r/MW-369.result @@ -1,25 +1,36 @@ +connection node_2; +connection node_1; CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1)) ; INSERT INTO p VALUES (1, 0); INSERT INTO p VALUES (2, 0); +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connection node_1; SET AUTOCOMMIT=ON; START TRANSACTION; DELETE FROM p WHERE f1 = 1; +connection node_1a; SET SESSION wsrep_sync_wait = 0; SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; INSERT INTO c VALUES (1, 1); +connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'dbug='; -SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync'; +connection node_1; COMMIT; +connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; -SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync'; SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +connection node_2; SELECT * FROM p; f1 f2 1 0 @@ -29,6 +40,7 @@ f1 p_id 1 1 DROP TABLE c; DROP TABLE p; +connection node_1; CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, f2 INTEGER, @@ -36,22 +48,30 @@ CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1)) ; INSERT INTO p VALUES (1, 0); INSERT INTO p VALUES (2, 0); INSERT INTO c VALUES (1, 1, 0); +connection node_1; SET AUTOCOMMIT=ON; START TRANSACTION; UPDATE p SET f2 = 1 WHERE f1 = 1; +connection node_1a; SET SESSION wsrep_sync_wait = 0; SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; UPDATE c SET f2 = 1 WHERE f1 = 1; +connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'dbug='; -SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync'; +connection node_1; COMMIT; +connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; -SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync'; SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; +connection node_2; SELECT * FROM p; f1 f2 1 1 @@ -61,28 +81,37 @@ f1 p_id f2 1 1 1 DROP TABLE c; DROP TABLE p; +connection node_1; CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1)) ; INSERT INTO p VALUES (1, 0); INSERT INTO p VALUES (2, 0); INSERT INTO c VALUES (1, 1); +connection node_1; SET AUTOCOMMIT=ON; START TRANSACTION; UPDATE p SET f2 = 1 WHERE f1 = 1; +connection node_1a; SET SESSION wsrep_sync_wait = 0; SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; DELETE FROM c WHERE f1 = 1; +connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'dbug='; -SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync'; +connection node_1; COMMIT; +connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; -SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync'; SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; +connection node_2; SELECT * FROM p; f1 f2 1 1 @@ -95,23 +124,31 @@ CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER UNIQUE KEY) ENGINE=INNODB; CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f2)) ; INSERT INTO p VALUES (1, 0); +connection node_1; SET AUTOCOMMIT=ON; START TRANSACTION; UPDATE p SET f2 = 1 WHERE f1 = 1; +connection node_1a; SET SESSION wsrep_sync_wait = 0; SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; INSERT INTO c VALUES (1, 0);; +connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'dbug='; -SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync'; +connection node_1; COMMIT; +connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; -SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync'; SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +connection node_2; SELECT * FROM p; f1 f2 1 0 @@ -127,23 +164,31 @@ ON DELETE CASCADE) ; INSERT INTO p VALUES (1, 0); INSERT INTO p VALUES (2, 0); INSERT INTO c VALUES (1, 1, 0); +connection node_1; SET AUTOCOMMIT=ON; START TRANSACTION; DELETE FROM p WHERE f1 = 1; +connection node_1a; SET SESSION wsrep_sync_wait = 0; SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; UPDATE c SET f2 = 1 WHERE f1 = 1; +connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'dbug='; -SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync'; +connection node_1; COMMIT; +connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; -SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync'; SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +connection node_2; SELECT * FROM p; f1 f2 1 0 diff --git a/mysql-test/suite/galera/r/MW-388.result b/mysql-test/suite/galera/r/MW-388.result index a2cf02712bb..114938c52d5 100644 --- a/mysql-test/suite/galera/r/MW-388.result +++ b/mysql-test/suite/galera/r/MW-388.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) Engine=InnoDB; CREATE PROCEDURE insert_proc () @@ -29,7 +31,7 @@ connection node_2; connection node_1; SELECT @errno = 1213; @errno = 1213 -0 +1 SELECT * FROM t1; f1 f2 1 node 2 diff --git a/mysql-test/suite/galera/r/MW-402.result b/mysql-test/suite/galera/r/MW-402.result index 9be98d629fb..f692c90d611 100644 --- a/mysql-test/suite/galera/r/MW-402.result +++ b/mysql-test/suite/galera/r/MW-402.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; connection node_1; CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; @@ -20,14 +22,14 @@ connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'dbug='; -SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync'; connection node_1; COMMIT; connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; -SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync'; SET GLOBAL wsrep_provider_options = 'dbug='; connection node_1; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction @@ -60,14 +62,14 @@ connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'dbug='; -SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync'; connection node_1; COMMIT; connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; -SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync'; SET GLOBAL wsrep_provider_options = 'dbug='; connection node_1; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction @@ -102,14 +104,14 @@ connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'dbug='; -SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync'; connection node_1; COMMIT; connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; -SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync'; SET GLOBAL wsrep_provider_options = 'dbug='; connection node_1; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction @@ -135,14 +137,14 @@ connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'dbug='; -SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync'; connection node_1; COMMIT; connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; -SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync'; SET GLOBAL wsrep_provider_options = 'dbug='; connection node_1; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction @@ -159,8 +161,10 @@ DROP TABLE p; connection node_1; CREATE TABLE p1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; CREATE TABLE p2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; -CREATE TABLE c (f1 INTEGER PRIMARY KEY, p1_id INTEGER, p2_id INTEGER, f2 INTEGER, -CONSTRAINT fk_1 FOREIGN KEY (p1_id) REFERENCES p1 (f1) ON DELETE CASCADE, +CREATE TABLE c (f1 INTEGER PRIMARY KEY, p1_id INTEGER, p2_id INTEGER, +f2 INTEGER, +CONSTRAINT fk_1 FOREIGN KEY (p1_id) REFERENCES p1 (f1) +ON DELETE CASCADE, CONSTRAINT fk_2 FOREIGN KEY (p2_id) REFERENCES p2 (f1)); INSERT INTO p1 VALUES (1, 0); INSERT INTO p2 VALUES (1, 0); @@ -179,14 +183,14 @@ connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'dbug='; -SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync'; connection node_1; COMMIT; connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; -SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync'; SET GLOBAL wsrep_provider_options = 'dbug='; connection node_1; connection node_2; @@ -197,4 +201,52 @@ f1 f2 1 2 SELECT * FROM c; f1 p1_id p2_id f2 +DROP TABLE c; +DROP TABLE p1; +DROP TABLE p2; +connection node_1; +CREATE TABLE p1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; +CREATE TABLE p2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; +CREATE TABLE c (f1 INTEGER PRIMARY KEY, p1_id INTEGER, p2_id INTEGER, +f2 INTEGER, +CONSTRAINT fk_1 FOREIGN KEY (p1_id) REFERENCES p1 (f1) +ON DELETE CASCADE, +CONSTRAINT fk_2 FOREIGN KEY (p2_id) REFERENCES p2 (f1) +ON DELETE CASCADE); +INSERT INTO p1 VALUES (1, 0); +INSERT INTO p2 VALUES (1, 0); +INSERT INTO c VALUES (1, 1, 1, 0); +connection node_1a; +connection node_1; +SET AUTOCOMMIT=ON; +START TRANSACTION; +DELETE FROM p2 WHERE f1=1; +connection node_1a; +SET SESSION wsrep_sync_wait = 0; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +DELETE FROM p1 WHERE f1=1; +connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync'; +connection node_1; +COMMIT; +connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync'; +SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +connection node_2; +SELECT * FROM p1; +f1 f2 +SELECT * FROM p2; +f1 f2 +1 0 +SELECT * FROM c; +f1 p1_id p2_id f2 DROP TABLE c,p1,p2; diff --git a/mysql-test/suite/galera/r/MW-416.result b/mysql-test/suite/galera/r/MW-416.result index 05399b213a8..9d72ae177b1 100644 --- a/mysql-test/suite/galera/r/MW-416.result +++ b/mysql-test/suite/galera/r/MW-416.result @@ -1,8 +1,9 @@ +connection node_2; +connection node_1; CREATE USER 'userMW416'@'localhost'; GRANT SELECT, INSERT, UPDATE ON test.* TO 'userMW416'@'localhost'; -SHOW GLOBAL STATUS LIKE 'wsrep_replicated'; -Variable_name Value -wsrep_replicated 2 +connect userMW416, localhost, userMW416,, test, $NODE_MYPORT_1; +connection userMW416; ALTER DATABASE db CHARACTER SET = utf8; ERROR 42000: Access denied for user 'userMW416'@'localhost' to database 'db' ALTER EVENT ev1 RENAME TO ev2; @@ -53,16 +54,12 @@ DROP FUNCTION fun1; Got one of the listed errors DROP INDEX idx ON t0; Got one of the listed errors -DROP LOGFILE GROUP lfg; -Got one of the listed errors DROP PROCEDURE proc1; Got one of the listed errors DROP SERVEr srv; Got one of the listed errors DROP TABLE t0; Got one of the listed errors -DROP TABLESPACE tblspc; -Got one of the listed errors DROP TRIGGER trg; Got one of the listed errors DROP VIEW vw; @@ -71,8 +68,6 @@ RENAME TABLE t0 TO t1; Got one of the listed errors TRUNCATE TABLE t0; Got one of the listed errors -ALTER USER myuser PASSWORD EXPIRE; -Got one of the listed errors CREATE USER myuser IDENTIFIED BY 'pass'; Got one of the listed errors DROP USER myuser; @@ -101,6 +96,7 @@ INSTALL PLUGIN plg SONAME 'plg.so'; Got one of the listed errors UNINSTALL PLUGIN plg; Got one of the listed errors +connection node_1; DROP USER 'userMW416'@'localhost'; SHOW DATABASES; Database @@ -109,6 +105,6 @@ mtr mysql performance_schema test -SHOW GLOBAL STATUS LIKE 'wsrep_replicated'; -Variable_name Value -wsrep_replicated 3 +wsrep_schema +wsrep_replicated_after_diff +1 diff --git a/mysql-test/suite/galera/r/MW-86-wait1.result b/mysql-test/suite/galera/r/MW-86-wait1.result index 00010eaedcb..36cbfadf302 100644 --- a/mysql-test/suite/galera/r/MW-86-wait1.result +++ b/mysql-test/suite/galera/r/MW-86-wait1.result @@ -1,11 +1,13 @@ connection node_2; +connection node_1; +SET @orig_debug=@@debug; +connection node_2; SELECT @@debug_sync; @@debug_sync ON - current signal: '' +set debug_sync='RESET'; SET SESSION wsrep_sync_wait = 1; -SET GLOBAL debug = "+d,sync.wsrep_apply_cb"; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +SET GLOBAL debug_dbug = "+d,sync.wsrep_apply_cb"; connection node_1; CREATE TABLE t_wait1 (f1 INTEGER) ENGINE=InnoDB; INSERT INTO t_wait1 VALUES (1); @@ -36,16 +38,11 @@ SHOW TABLES; SHOW TRIGGERS; SHOW GLOBAL VARIABLES LIKE 'foo_bar'; SHOW WARNINGS; -SET GLOBAL debug = "-d,sync.wsrep_apply_cb"; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +SET GLOBAL debug_dbug = @orig_debug; SET SESSION debug_sync = "now SIGNAL signal.wsrep_apply_cb"; +SET debug_sync='RESET'; SET SESSION wsrep_sync_wait = default; DROP TABLE t_wait1; -SET GLOBAL debug = NULL; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead -SET debug_sync='RESET'; SELECT @@debug_sync; @@debug_sync ON - current signal: '' diff --git a/mysql-test/suite/galera/r/MW-86-wait8.result b/mysql-test/suite/galera/r/MW-86-wait8.result index 47e0ebc1342..6ac2c5f5e1f 100644 --- a/mysql-test/suite/galera/r/MW-86-wait8.result +++ b/mysql-test/suite/galera/r/MW-86-wait8.result @@ -1,11 +1,12 @@ connection node_2; +connection node_1; +SET @orig_debug=@@debug; +connection node_2; SELECT @@debug_sync; @@debug_sync ON - current signal: '' SET SESSION wsrep_sync_wait = 8; -SET GLOBAL debug = "+d,sync.wsrep_apply_cb"; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +SET GLOBAL debug_dbug = "+d,sync.wsrep_apply_cb"; connection node_1; CREATE TABLE t_wait8 (f1 INTEGER) ENGINE=InnoDB; INSERT INTO t_wait8 VALUES (1); @@ -38,16 +39,11 @@ SHOW TABLES; SHOW TRIGGERS; SHOW GLOBAL VARIABLES LIKE 'foo_bar'; SHOW WARNINGS; -SET GLOBAL debug = "-d,sync.wsrep_apply_cb"; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +SET GLOBAL debug_dbug = @orig_debug; SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; +SET debug_sync='RESET'; SET SESSION wsrep_sync_wait = default; DROP TABLE t_wait8; -SET GLOBAL debug = NULL; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead -SET debug_sync='RESET'; SELECT @@debug_sync; @@debug_sync ON - current signal: '' diff --git a/mysql-test/suite/galera/r/MW-86.result b/mysql-test/suite/galera/r/MW-86.result new file mode 100644 index 00000000000..bca9be93191 --- /dev/null +++ b/mysql-test/suite/galera/r/MW-86.result @@ -0,0 +1,78 @@ +connection node_2; +connection node_1; +connection node_2; +SET SESSION wsrep_sync_wait = 1; +SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +connection node_1; +CREATE DATABASE db1; +CREATE TABLE bar (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO bar VALUES (1); +connection node_2; +SHOW BINARY LOGS; +SHOW BINLOG EVENTS; +SHOW COLUMNS FROM t1; +SHOW CREATE DATABASE db1; +SHOW CREATE EVENT e1; +SHOW CREATE FUNCTION f1; +SHOW CREATE PROCEDURE p1; +SHOW CREATE TABLE t1; +SHOW CREATE TRIGGER tr1; +SHOW CREATE VIEW v1; +SHOW DATABASES; +SHOW ENGINE InnoDB STATUS; +SHOW FUNCTION CODE f1; +SHOW FUNCTION STATUS; +SHOW GRANTS FOR 'root'@'localhost'; +SHOW INDEX FROM t1; +SHOW OPEN TABLES; +SHOW PROCEDURE CODE p1; +SHOW PROCEDURE STATUS; +SHOW PRIVILEGES; +SHOW STATUS LIKE 'wsrep_cluster_size'; +SHOW TABLE STATUS; +SHOW TABLES; +SHOW TRIGGERS; +SHOW GLOBAL VARIABLES LIKE 'foo_bar'; +SHOW WARNINGS; +SET GLOBAL DEBUG = ""; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; +SET SESSION wsrep_sync_wait = 8; +DROP DATABASE db1; +connection node_2; +SET GLOBAL wsrep_provider_options = "repl.causal_read_timeout=PT0.1S"; +SET SESSION wsrep_sync_wait = 8; +SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; +connection node_1; +CREATE TABLE q (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO q VALUES (1); +connection node_2; +SHOW BINARY LOGS; +SHOW BINLOG EVENTS; +SHOW COLUMNS FROM t1; +SHOW CREATE DATABASE db1; +SHOW CREATE EVENT e1; +SHOW CREATE FUNCTION f1; +SHOW CREATE PROCEDURE p1; +SHOW CREATE TABLE t1; +SHOW CREATE TRIGGER tr1; +SHOW CREATE VIEW v1; +SHOW DATABASES; +SHOW ENGINE InnoDB STATUS; +SHOW FUNCTION CODE f1; +SHOW FUNCTION STATUS; +SHOW GRANTS FOR 'root'@'localhost'; +SHOW INDEX FROM t1; +SHOW OPEN TABLES; +SHOW PROCEDURE CODE p1; +SHOW PROCEDURE STATUS; +SHOW PRIVILEGES; +SHOW STATUS LIKE 'wsrep_cluster_size'; +SHOW TABLE STATUS; +SHOW TABLES; +SHOW TRIGGERS; +SHOW GLOBAL VARIABLES LIKE 'foo_bar'; +SHOW WARNINGS; +SET GLOBAL DEBUG = ""; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; diff --git a/mysql-test/suite/galera/r/basic.result b/mysql-test/suite/galera/r/basic.result index e85c805253f..10f180e7a94 100644 --- a/mysql-test/suite/galera/r/basic.result +++ b/mysql-test/suite/galera/r/basic.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; USE test; CREATE TABLE t1(c1 INT PRIMARY KEY) ENGINE=INNODB; INSERT INTO t1 VALUES (1), (2), (3), (4), (5); diff --git a/mysql-test/suite/galera/r/binlog_checksum.result b/mysql-test/suite/galera/r/binlog_checksum.result index e86f3892ac7..4106354eb7d 100644 --- a/mysql-test/suite/galera/r/binlog_checksum.result +++ b/mysql-test/suite/galera/r/binlog_checksum.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; # On node_1 connection node_1; SET @binlog_checksum_saved= @@GLOBAL.BINLOG_CHECKSUM; diff --git a/mysql-test/suite/galera/r/create.result b/mysql-test/suite/galera/r/create.result index a445b32e8bf..6ad94dd3d43 100644 --- a/mysql-test/suite/galera/r/create.result +++ b/mysql-test/suite/galera/r/create.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; # # MDEV-6924 : Server crashed on CREATE TABLE ... SELECT # diff --git a/mysql-test/suite/galera/r/enforce_storage_engine.result b/mysql-test/suite/galera/r/enforce_storage_engine.result index 746aa22bf20..1a453241427 100644 --- a/mysql-test/suite/galera/r/enforce_storage_engine.result +++ b/mysql-test/suite/galera/r/enforce_storage_engine.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; # # MDEV-8831 : enforce_storage_engine doesn't block table creation on # other nodes (galera cluster) diff --git a/mysql-test/suite/galera/r/enforce_storage_engine2.result b/mysql-test/suite/galera/r/enforce_storage_engine2.result index 128994ed221..8b174139eae 100644 --- a/mysql-test/suite/galera/r/enforce_storage_engine2.result +++ b/mysql-test/suite/galera/r/enforce_storage_engine2.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; # # MDEV-9312: storage engine not enforced during galera cluster # replication diff --git a/mysql-test/suite/galera/r/ev51914.result b/mysql-test/suite/galera/r/ev51914.result index 3f3d67d01ef..b9d8a82bfa0 100644 --- a/mysql-test/suite/galera/r/ev51914.result +++ b/mysql-test/suite/galera/r/ev51914.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; SAVEPOINT in a stored function should be forbidden CREATE FUNCTION f1 () RETURNS INT BEGIN diff --git a/mysql-test/suite/galera/r/fk.result b/mysql-test/suite/galera/r/fk.result index ab8e1c8f680..17fc99a904e 100644 --- a/mysql-test/suite/galera/r/fk.result +++ b/mysql-test/suite/galera/r/fk.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; USE test; # On node_1 diff --git a/mysql-test/suite/galera/r/galera#414.result b/mysql-test/suite/galera/r/galera#414.result index 34dcb6242d3..2c1dccfd131 100644 --- a/mysql-test/suite/galera/r/galera#414.result +++ b/mysql-test/suite/galera/r/galera#414.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; connection node_2; connection node_2; diff --git a/mysql-test/suite/galera/r/galera#500.result b/mysql-test/suite/galera/r/galera#500.result index 6a07d0359a4..22d38777369 100644 --- a/mysql-test/suite/galera/r/galera#500.result +++ b/mysql-test/suite/galera/r/galera#500.result @@ -1,10 +1,16 @@ +connection node_2; +connection node_1; +connection node_2; SET SESSION wsrep_sync_wait = 0; SET GLOBAL wsrep_provider_options="gmcast.isolate=2"; +connection node_1; SET SESSION wsrep_sync_wait = 0; SHOW STATUS LIKE 'wsrep_cluster_status'; Variable_name Value wsrep_cluster_status non-Primary SET SESSION wsrep_sync_wait = default; SET GLOBAL wsrep_provider_options="pc.bootstrap=1"; +connection node_2; SET SESSION wsrep_on=0; +connection node_2; CALL mtr.add_suppression("WSREP: exception from gcomm, backend must be restarted: Gcomm backend termination was requested by setting gmcast.isolate=2."); diff --git a/mysql-test/suite/galera/r/galera_admin.result b/mysql-test/suite/galera/r/galera_admin.result index ed753247236..3db60e99409 100644 --- a/mysql-test/suite/galera/r/galera_admin.result +++ b/mysql-test/suite/galera/r/galera_admin.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; DROP TABLE IF EXISTS t1, t2; DROP TABLE IF EXISTS x1, x2; connection node_1; diff --git a/mysql-test/suite/galera/r/galera_alter_engine_innodb.result b/mysql-test/suite/galera/r/galera_alter_engine_innodb.result index ff6ab792c0e..dfa30441f85 100644 --- a/mysql-test/suite/galera/r/galera_alter_engine_innodb.result +++ b/mysql-test/suite/galera/r/galera_alter_engine_innodb.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); ALTER TABLE t1 ENGINE=InnoDB; diff --git a/mysql-test/suite/galera/r/galera_alter_engine_myisam.result b/mysql-test/suite/galera/r/galera_alter_engine_myisam.result index 389383858ac..b3a9bdd30df 100644 --- a/mysql-test/suite/galera/r/galera_alter_engine_myisam.result +++ b/mysql-test/suite/galera/r/galera_alter_engine_myisam.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; SET GLOBAL wsrep_replicate_myisam = TRUE; CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM; INSERT INTO t1 VALUES (1); diff --git a/mysql-test/suite/galera/r/galera_alter_table_force.result b/mysql-test/suite/galera/r/galera_alter_table_force.result index d0a2f81b631..271796422cd 100644 --- a/mysql-test/suite/galera/r/galera_alter_table_force.result +++ b/mysql-test/suite/galera/r/galera_alter_table_force.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); ALTER TABLE t1 FORCE; diff --git a/mysql-test/suite/galera/r/galera_applier_ftwrl_table.result b/mysql-test/suite/galera/r/galera_applier_ftwrl_table.result index a6607906661..11fda5d8aab 100644 --- a/mysql-test/suite/galera/r/galera_applier_ftwrl_table.result +++ b/mysql-test/suite/galera/r/galera_applier_ftwrl_table.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; SET SESSION wsrep_sync_wait = 0; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; diff --git a/mysql-test/suite/galera/r/galera_applier_ftwrl_table_alter.result b/mysql-test/suite/galera/r/galera_applier_ftwrl_table_alter.result index 9711100d155..a5aeb6eb366 100644 --- a/mysql-test/suite/galera/r/galera_applier_ftwrl_table_alter.result +++ b/mysql-test/suite/galera/r/galera_applier_ftwrl_table_alter.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; SET SESSION wsrep_sync_wait = 0; SET SESSION lock_wait_timeout = 60; diff --git a/mysql-test/suite/galera/r/galera_as_master.result b/mysql-test/suite/galera/r/galera_as_master.result index 2a7262359fa..4aca328be56 100644 --- a/mysql-test/suite/galera/r/galera_as_master.result +++ b/mysql-test/suite/galera/r/galera_as_master.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; START SLAVE; connection node_1; @@ -54,4 +56,6 @@ STOP SLAVE; RESET SLAVE ALL; CALL mtr.add_suppression('You need to use --log-bin to make --binlog-format work'); connection node_1; +set global wsrep_on=OFF; RESET MASTER; +set global wsrep_on=ON; diff --git a/mysql-test/suite/galera/r/galera_as_master_gtid.result b/mysql-test/suite/galera/r/galera_as_master_gtid.result index 8dfe462d495..4f5c38b607a 100644 --- a/mysql-test/suite/galera/r/galera_as_master_gtid.result +++ b/mysql-test/suite/galera/r/galera_as_master_gtid.result @@ -5,55 +5,19 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES(1); uuids_do_not_match 1 -SHOW BINLOG EVENTS IN 'mysqld-bin.000002' FROM 120; -Log_name Pos Event_type Server_id End_log_pos Info -mysqld-bin.000002 120 Previous_gtids 1 151 -mysqld-bin.000002 151 Gtid 1 199 SET @@SESSION.GTID_NEXT= '<effective_uuid>:1' -mysqld-bin.000002 199 Query 1 327 use `test`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB -mysqld-bin.000002 327 Gtid 1 375 SET @@SESSION.GTID_NEXT= '<effective_uuid>:2' -mysqld-bin.000002 375 Query 1 452 BEGIN -mysqld-bin.000002 452 Table_map 1 497 table_id: # (test.t1) -mysqld-bin.000002 497 Write_rows 1 537 table_id: # flags: STMT_END_F -mysqld-bin.000002 537 Xid 1 568 COMMIT /* xid=# */ INSERT INTO t1 VALUES(2); uuids_do_not_match 1 uuids_match 1 -SHOW BINLOG EVENTS IN 'mysqld-bin.000003' FROM 120; -Log_name Pos Event_type Server_id End_log_pos Info -mysqld-bin.000003 120 Previous_gtids 2 151 -mysqld-bin.000003 151 Gtid 1 199 SET @@SESSION.GTID_NEXT= '<effective_uuid>:1' -mysqld-bin.000003 199 Query 1 327 use `test`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB -mysqld-bin.000003 327 Gtid 1 375 SET @@SESSION.GTID_NEXT= '<effective_uuid>:2' -mysqld-bin.000003 375 Query 1 443 BEGIN -mysqld-bin.000003 443 Table_map 1 488 table_id: # (test.t1) -mysqld-bin.000003 488 Write_rows 1 528 table_id: # flags: STMT_END_F -mysqld-bin.000003 528 Xid 1 559 COMMIT /* xid=# */ -mysqld-bin.000003 559 Gtid 2 607 SET @@SESSION.GTID_NEXT= '<effective_uuid>:3' -mysqld-bin.000003 607 Query 2 684 BEGIN -mysqld-bin.000003 684 Table_map 2 729 table_id: # (test.t1) -mysqld-bin.000003 729 Write_rows 2 769 table_id: # flags: STMT_END_F -mysqld-bin.000003 769 Xid 2 800 COMMIT /* xid=# */ uuids_do_not_match 1 uuids_match 1 -SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 120; -Log_name Pos Event_type Server_id End_log_pos Info -mysqld-bin.000001 120 Previous_gtids 3 151 -mysqld-bin.000001 151 Gtid 1 199 SET @@SESSION.GTID_NEXT= '<effective_uuid>:1' -mysqld-bin.000001 199 Query 1 327 use `test`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB -mysqld-bin.000001 327 Gtid 1 375 SET @@SESSION.GTID_NEXT= '<effective_uuid>:2' -mysqld-bin.000001 375 Query 1 443 BEGIN -mysqld-bin.000001 443 Table_map 1 488 table_id: # (test.t1) -mysqld-bin.000001 488 Write_rows 1 528 table_id: # flags: STMT_END_F -mysqld-bin.000001 528 Xid 1 559 COMMIT /* xid=# */ -mysqld-bin.000001 559 Gtid 2 607 SET @@SESSION.GTID_NEXT= '<effective_uuid>:3' -mysqld-bin.000001 607 Query 2 675 BEGIN -mysqld-bin.000001 675 Table_map 2 720 table_id: # (test.t1) -mysqld-bin.000001 720 Write_rows 2 760 table_id: # flags: STMT_END_F -mysqld-bin.000001 760 Xid 2 791 COMMIT /* xid=# */ DROP TABLE t1; +gtid_executed_equal +1 +gtid_executed_equal +1 STOP SLAVE; RESET SLAVE ALL; diff --git a/mysql-test/suite/galera/r/galera_as_master_large.result b/mysql-test/suite/galera/r/galera_as_master_large.result index dad74211af9..826d2f32057 100644 --- a/mysql-test/suite/galera/r/galera_as_master_large.result +++ b/mysql-test/suite/galera/r/galera_as_master_large.result @@ -2,6 +2,8 @@ # MDEV-9044 : Getting binlog corruption on my Galera cluster (10.1.8) # making it impossible to async slave. # +connection node_2; +connection node_1; connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; START SLAVE; connection node_1; diff --git a/mysql-test/suite/galera/r/galera_as_slave_autoinc.result b/mysql-test/suite/galera/r/galera_as_slave_autoinc.result index 60f3216aa9c..2da72af0d9b 100644 --- a/mysql-test/suite/galera/r/galera_as_slave_autoinc.result +++ b/mysql-test/suite/galera/r/galera_as_slave_autoinc.result @@ -1,5 +1,7 @@ connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; connection node_2; +connection node_1; +connection node_2; START SLAVE; connection node_1; SET SESSION binlog_format='STATEMENT'; @@ -85,4 +87,6 @@ connection node_2; STOP SLAVE; RESET SLAVE ALL; connection node_1; +SET GLOBAL wsrep_on=OFF; RESET MASTER; +SET GLOBAL wsrep_on=ON; diff --git a/mysql-test/suite/galera/r/galera_as_slave_gtid.result b/mysql-test/suite/galera/r/galera_as_slave_gtid.result index 0ef9d208bf4..1262879d992 100644 --- a/mysql-test/suite/galera/r/galera_as_slave_gtid.result +++ b/mysql-test/suite/galera/r/galera_as_slave_gtid.result @@ -1,5 +1,7 @@ connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; connection node_2; +connection node_1; +connection node_2; START SLAVE; connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; diff --git a/mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db.result b/mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db.result new file mode 100644 index 00000000000..9f10efccd22 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db.result @@ -0,0 +1,160 @@ +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_2; +connection node_1; +connection node_1; +RESET MASTER; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_3; +SET global wsrep_on=OFF; +RESET MASTER; +SET global wsrep_on=ON; +connection node_2; +SET global wsrep_on=OFF; +RESET MASTER; +SET global wsrep_on=ON; +START SLAVE; +connection node_1; +CREATE SCHEMA test1; +CREATE SCHEMA test2; +USE test1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY,f2 CHAR(5) DEFAULT 'abc') ENGINE=InnoDB; +USE test2; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY,f2 CHAR(5) DEFAULT 'abc') ENGINE=InnoDB; +INSERT INTO test1.t1 (f1) VALUES (1); +INSERT INTO test2.t1 (f1) VALUES (1); +INSERT INTO test1.t1 (f1) VALUES (2); +INSERT INTO test2.t1 (f1) VALUES (2); +INSERT INTO test1.t1 (f1) VALUES (3); +INSERT INTO test2.t1 (f1) VALUES (3); +UPDATE test2.t1 SET test2.t1.f2 = 'cde'; +UPDATE test1.t1, test2.t1 SET test1.t1.f2 = 'klm', test2.t1.f2 = 'xyz'; +DELETE test1.t1, test2.t1 FROM test1.t1 INNER JOIN test2.t1 WHERE test1.t1.f1 = test2.t1.f1 AND test1.t1.f1 = 3; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO test2.t1 (f1) VALUES (999); +INSERT INTO test2.t1 (f1) VALUES (9999); +COMMIT; +START TRANSACTION; +INSERT INTO test1.t1 (f1) VALUES (111); +INSERT INTO test1.t1 (f1) VALUES (222); +COMMIT; +START TRANSACTION; +INSERT INTO test1.t1 (f1) VALUES (333); +INSERT INTO test2.t1 (f1) VALUES (99999); +COMMIT; +connection node_2; +SHOW BINLOG EVENTS IN 'master-bin.000001' FROM 256; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 256 Gtid_list 2 285 [] +master-bin.000001 285 Binlog_checkpoint 2 329 master-bin.000001 +master-bin.000001 329 Gtid 1 371 GTID 0-1-1 +master-bin.000001 371 Query 1 458 CREATE SCHEMA test1 +master-bin.000001 458 Gtid 1 500 GTID 0-1-3 +master-bin.000001 500 Query 1 647 use `test1`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY,f2 CHAR(5) DEFAULT 'abc') ENGINE=InnoDB +master-bin.000001 647 Gtid 1 689 BEGIN GTID 0-1-5 +master-bin.000001 689 Annotate_rows 1 748 INSERT INTO test1.t1 (f1) VALUES (1) +master-bin.000001 748 Table_map 1 797 table_id: ### (test1.t1) +master-bin.000001 797 Write_rows_v1 1 839 table_id: ### flags: STMT_END_F +master-bin.000001 839 Xid 1 870 COMMIT /* xid=### */ +master-bin.000001 870 Gtid 1 912 BEGIN GTID 0-1-7 +master-bin.000001 912 Annotate_rows 1 971 INSERT INTO test1.t1 (f1) VALUES (2) +master-bin.000001 971 Table_map 1 1020 table_id: ### (test1.t1) +master-bin.000001 1020 Write_rows_v1 1 1062 table_id: ### flags: STMT_END_F +master-bin.000001 1062 Xid 1 1093 COMMIT /* xid=### */ +master-bin.000001 1093 Gtid 1 1135 BEGIN GTID 0-1-9 +master-bin.000001 1135 Annotate_rows 1 1194 INSERT INTO test1.t1 (f1) VALUES (3) +master-bin.000001 1194 Table_map 1 1243 table_id: ### (test1.t1) +master-bin.000001 1243 Write_rows_v1 1 1285 table_id: ### flags: STMT_END_F +master-bin.000001 1285 Xid 1 1316 COMMIT /* xid=### */ +master-bin.000001 1316 Gtid 1 1358 BEGIN GTID 0-1-12 +master-bin.000001 1358 Annotate_rows 1 1451 UPDATE test1.t1, test2.t1 SET test1.t1.f2 = 'klm', test2.t1.f2 = 'xyz' +master-bin.000001 1451 Table_map 1 1500 table_id: ### (test1.t1) +master-bin.000001 1500 Update_rows_v1 1 1588 table_id: ### flags: STMT_END_F +master-bin.000001 1588 Xid 1 1619 COMMIT /* xid=### */ +master-bin.000001 1619 Gtid 1 1661 BEGIN GTID 0-1-13 +master-bin.000001 1661 Annotate_rows 1 1795 DELETE test1.t1, test2.t1 FROM test1.t1 INNER JOIN test2.t1 WHERE test1.t1.f1 = test2.t1.f1 AND test1.t1.f1 = 3 +master-bin.000001 1795 Table_map 1 1844 table_id: ### (test1.t1) +master-bin.000001 1844 Delete_rows_v1 1 1886 table_id: ### flags: STMT_END_F +master-bin.000001 1886 Xid 1 1917 COMMIT /* xid=### */ +master-bin.000001 1917 Gtid 1 1959 BEGIN GTID 0-1-15 +master-bin.000001 1959 Annotate_rows 1 2020 INSERT INTO test1.t1 (f1) VALUES (111) +master-bin.000001 2020 Table_map 1 2069 table_id: ### (test1.t1) +master-bin.000001 2069 Write_rows_v1 1 2111 table_id: ### flags: STMT_END_F +master-bin.000001 2111 Annotate_rows 1 2172 INSERT INTO test1.t1 (f1) VALUES (222) +master-bin.000001 2172 Table_map 1 2221 table_id: ### (test1.t1) +master-bin.000001 2221 Write_rows_v1 1 2263 table_id: ### flags: STMT_END_F +master-bin.000001 2263 Xid 1 2294 COMMIT /* xid=### */ +master-bin.000001 2294 Gtid 1 2336 BEGIN GTID <effective_uuid> +master-bin.000001 2336 Annotate_rows 1 2397 INSERT INTO test1.t1 (f1) VALUES (333) +master-bin.000001 2397 Table_map 1 2446 table_id: ### (test1.t1) +master-bin.000001 2446 Write_rows_v1 1 2488 table_id: ### flags: STMT_END_F +master-bin.000001 2488 Xid 1 2519 COMMIT /* xid=### */ +connection node_3; +gtid_executed_equal +0 +SHOW BINLOG EVENTS IN 'master-bin.000001' FROM 256; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 256 Gtid_list 3 285 [] +master-bin.000001 285 Binlog_checkpoint 3 329 master-bin.000001 +master-bin.000001 329 Gtid 1 371 GTID 0-1-1 +master-bin.000001 371 Query 1 458 CREATE SCHEMA test1 +master-bin.000001 458 Gtid 1 500 GTID 0-1-2 +master-bin.000001 500 Query 1 647 use `test1`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY,f2 CHAR(5) DEFAULT 'abc') ENGINE=InnoDB +master-bin.000001 647 Gtid 1 689 BEGIN GTID 0-1-3 +master-bin.000001 689 Annotate_rows 1 748 INSERT INTO test1.t1 (f1) VALUES (1) +master-bin.000001 748 Table_map 1 797 table_id: ### (test1.t1) +master-bin.000001 797 Write_rows_v1 1 839 table_id: ### flags: STMT_END_F +master-bin.000001 839 Xid 1 870 COMMIT /* xid=### */ +master-bin.000001 870 Gtid 1 912 BEGIN GTID 0-1-4 +master-bin.000001 912 Annotate_rows 1 971 INSERT INTO test1.t1 (f1) VALUES (2) +master-bin.000001 971 Table_map 1 1020 table_id: ### (test1.t1) +master-bin.000001 1020 Write_rows_v1 1 1062 table_id: ### flags: STMT_END_F +master-bin.000001 1062 Xid 1 1093 COMMIT /* xid=### */ +master-bin.000001 1093 Gtid 1 1135 BEGIN GTID 0-1-5 +master-bin.000001 1135 Annotate_rows 1 1194 INSERT INTO test1.t1 (f1) VALUES (3) +master-bin.000001 1194 Table_map 1 1243 table_id: ### (test1.t1) +master-bin.000001 1243 Write_rows_v1 1 1285 table_id: ### flags: STMT_END_F +master-bin.000001 1285 Xid 1 1316 COMMIT /* xid=### */ +master-bin.000001 1316 Gtid 1 1358 BEGIN GTID 0-1-6 +master-bin.000001 1358 Annotate_rows 1 1451 UPDATE test1.t1, test2.t1 SET test1.t1.f2 = 'klm', test2.t1.f2 = 'xyz' +master-bin.000001 1451 Table_map 1 1500 table_id: ### (test1.t1) +master-bin.000001 1500 Update_rows_v1 1 1588 table_id: ### flags: STMT_END_F +master-bin.000001 1588 Xid 1 1619 COMMIT /* xid=### */ +master-bin.000001 1619 Gtid 1 1661 BEGIN GTID 0-1-7 +master-bin.000001 1661 Annotate_rows 1 1795 DELETE test1.t1, test2.t1 FROM test1.t1 INNER JOIN test2.t1 WHERE test1.t1.f1 = test2.t1.f1 AND test1.t1.f1 = 3 +master-bin.000001 1795 Table_map 1 1844 table_id: ### (test1.t1) +master-bin.000001 1844 Delete_rows_v1 1 1886 table_id: ### flags: STMT_END_F +master-bin.000001 1886 Xid 1 1917 COMMIT /* xid=### */ +master-bin.000001 1917 Gtid 1 1959 BEGIN GTID 0-1-8 +master-bin.000001 1959 Annotate_rows 1 2020 INSERT INTO test1.t1 (f1) VALUES (111) +master-bin.000001 2020 Table_map 1 2069 table_id: ### (test1.t1) +master-bin.000001 2069 Write_rows_v1 1 2111 table_id: ### flags: STMT_END_F +master-bin.000001 2111 Annotate_rows 1 2172 INSERT INTO test1.t1 (f1) VALUES (222) +master-bin.000001 2172 Table_map 1 2221 table_id: ### (test1.t1) +master-bin.000001 2221 Write_rows_v1 1 2263 table_id: ### flags: STMT_END_F +master-bin.000001 2263 Xid 1 2294 COMMIT /* xid=### */ +master-bin.000001 2294 Gtid 1 2336 BEGIN GTID 0-1-9 +master-bin.000001 2336 Annotate_rows 1 2397 INSERT INTO test1.t1 (f1) VALUES (333) +master-bin.000001 2397 Table_map 1 2446 table_id: ### (test1.t1) +master-bin.000001 2446 Write_rows_v1 1 2488 table_id: ### flags: STMT_END_F +master-bin.000001 2488 Xid 1 2519 COMMIT /* xid=### */ +include/diff_servers.inc [servers=2 3] +connection node_3; +SELECT COUNT(*) = 2 FROM test1.t1 WHERE f1 IN (1,2); +COUNT(*) = 2 +1 +SELECT COUNT(*) = 3 FROM test1.t1 WHERE f1 IN (111,222,333); +COUNT(*) = 3 +1 +SELECT COUNT(*) = 2 FROM test1.t1 WHERE f2 = 'klm'; +COUNT(*) = 2 +1 +USE test2; +ERROR 42000: Unknown database 'test2' +connection node_1; +DROP SCHEMA test1; +DROP SCHEMA test2; +connection node_3; +connection node_2; +STOP SLAVE; +RESET SLAVE ALL; diff --git a/mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db_cc.result b/mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db_cc.result new file mode 100644 index 00000000000..fc10cc01a45 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db_cc.result @@ -0,0 +1,315 @@ +RESET MASTER; +SET global wsrep_on=OFF; +RESET MASTER; +SET global wsrep_on=ON; +SET global wsrep_on=OFF; +RESET MASTER; +SET global wsrep_on=ON; +START SLAVE USER='root'; +Warnings: +Note 1759 Sending passwords in plain text without SSL/TLS is extremely insecure. +CREATE SCHEMA test1; +CREATE SCHEMA test2; +USE test1; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +USE test2; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO test1.t1 (f1) VALUES (1); +INSERT INTO test2.t1 (f1) VALUES (1); +INSERT INTO test1.t1 (f1) VALUES (2); +INSERT INTO test2.t1 (f1) VALUES (2); +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +INSERT INTO test1.t1 (f1) VALUES (3); +INSERT INTO test2.t1 (f1) VALUES (3); +INSERT INTO test1.t1 (f1) VALUES (3); +INSERT INTO test2.t1 (f1) VALUES (3); +INSERT INTO test1.t1 (f1) VALUES (3); +INSERT INTO test2.t1 (f1) VALUES (3); +INSERT INTO test1.t1 (f1) VALUES (3); +INSERT INTO test2.t1 (f1) VALUES (3); +SET SESSION wsrep_on=OFF; +include/wait_for_slave_sql_error.inc [errno=1047] +INSERT INTO test1.t1 (f1) VALUES (4); +INSERT INTO test2.t1 (f1) VALUES (4); +INSERT INTO test1.t1 (f1) VALUES (4); +INSERT INTO test2.t1 (f1) VALUES (4); +INSERT INTO test1.t1 (f1) VALUES (4); +INSERT INTO test2.t1 (f1) VALUES (4); +INSERT INTO test1.t1 (f1) VALUES (4); +INSERT INTO test2.t1 (f1) VALUES (4); +INSERT INTO test1.t1 (f1) VALUES (4); +INSERT INTO test2.t1 (f1) VALUES (4); +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +INSERT INTO test1.t1 (f1) VALUES (5); +INSERT INTO test2.t1 (f1) VALUES (5); +SET SESSION wsrep_on=ON; +INSERT INTO test1.t1 (f1) VALUES (6); +INSERT INTO test2.t1 (f1) VALUES (6); +START SLAVE; +SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 120; +Log_name Pos Event_type Server_id End_log_pos Info +mysqld-bin.000001 120 Previous_gtids 2 151 +mysqld-bin.000001 151 Gtid 1 199 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:1' +mysqld-bin.000001 199 Query 1 294 CREATE SCHEMA test1 +mysqld-bin.000001 294 Gtid 1 342 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:2' +mysqld-bin.000001 342 Query 1 415 BEGIN +mysqld-bin.000001 415 Query 1 489 COMMIT +mysqld-bin.000001 489 Gtid 1 537 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:3' +mysqld-bin.000001 537 Query 1 655 use `test1`; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB +mysqld-bin.000001 655 Gtid 1 703 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:4' +mysqld-bin.000001 703 Query 1 776 BEGIN +mysqld-bin.000001 776 Query 1 850 COMMIT +mysqld-bin.000001 850 Gtid 1 898 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:5' +mysqld-bin.000001 898 Query 1 961 BEGIN +mysqld-bin.000001 961 Table_map 1 1007 table_id: ### (test1.t1) +mysqld-bin.000001 1007 Write_rows 1 1047 table_id: ### flags: STMT_END_F +mysqld-bin.000001 1047 Xid 1 1078 COMMIT /* xid=### */ +mysqld-bin.000001 1078 Gtid 1 1126 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:6' +mysqld-bin.000001 1126 Query 1 1189 BEGIN +mysqld-bin.000001 1189 Query 1 1253 COMMIT +mysqld-bin.000001 1253 Gtid 1 1301 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:7' +mysqld-bin.000001 1301 Query 1 1364 BEGIN +mysqld-bin.000001 1364 Table_map 1 1410 table_id: ### (test1.t1) +mysqld-bin.000001 1410 Write_rows 1 1450 table_id: ### flags: STMT_END_F +mysqld-bin.000001 1450 Xid 1 1481 COMMIT /* xid=### */ +mysqld-bin.000001 1481 Gtid 1 1529 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:8' +mysqld-bin.000001 1529 Query 1 1592 BEGIN +mysqld-bin.000001 1592 Query 1 1656 COMMIT +mysqld-bin.000001 1656 Gtid 2 1704 SET @@SESSION.GTID_NEXT= '<effective_uuid_2>:12' +mysqld-bin.000001 1704 Query 2 1772 BEGIN +mysqld-bin.000001 1772 Ignorable 2 1795 # Unrecognized ignorable event +mysqld-bin.000001 1795 Query 2 1864 COMMIT +mysqld-bin.000001 1864 Gtid 2 1912 SET @@SESSION.GTID_NEXT= '<effective_uuid_2>:13' +mysqld-bin.000001 1912 Query 2 1980 BEGIN +mysqld-bin.000001 1980 Ignorable 2 2003 # Unrecognized ignorable event +mysqld-bin.000001 2003 Query 2 2072 COMMIT +mysqld-bin.000001 2072 Gtid 1 2120 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:9' +mysqld-bin.000001 2120 Query 1 2183 BEGIN +mysqld-bin.000001 2183 Table_map 1 2229 table_id: ### (test1.t1) +mysqld-bin.000001 2229 Write_rows 1 2269 table_id: ### flags: STMT_END_F +mysqld-bin.000001 2269 Xid 1 2300 COMMIT /* xid=### */ +mysqld-bin.000001 2300 Gtid 1 2348 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:10' +mysqld-bin.000001 2348 Query 1 2411 BEGIN +mysqld-bin.000001 2411 Query 1 2475 COMMIT +mysqld-bin.000001 2475 Gtid 1 2523 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:11' +mysqld-bin.000001 2523 Query 1 2586 BEGIN +mysqld-bin.000001 2586 Table_map 1 2632 table_id: ### (test1.t1) +mysqld-bin.000001 2632 Write_rows 1 2672 table_id: ### flags: STMT_END_F +mysqld-bin.000001 2672 Xid 1 2703 COMMIT /* xid=### */ +mysqld-bin.000001 2703 Gtid 1 2751 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:12' +mysqld-bin.000001 2751 Query 1 2814 BEGIN +mysqld-bin.000001 2814 Query 1 2878 COMMIT +mysqld-bin.000001 2878 Gtid 1 2926 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:13' +mysqld-bin.000001 2926 Query 1 2989 BEGIN +mysqld-bin.000001 2989 Table_map 1 3035 table_id: ### (test1.t1) +mysqld-bin.000001 3035 Write_rows 1 3075 table_id: ### flags: STMT_END_F +mysqld-bin.000001 3075 Xid 1 3106 COMMIT /* xid=### */ +mysqld-bin.000001 3106 Gtid 1 3154 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:14' +mysqld-bin.000001 3154 Query 1 3217 BEGIN +mysqld-bin.000001 3217 Query 1 3281 COMMIT +mysqld-bin.000001 3281 Gtid 1 3329 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:15' +mysqld-bin.000001 3329 Query 1 3392 BEGIN +mysqld-bin.000001 3392 Table_map 1 3438 table_id: ### (test1.t1) +mysqld-bin.000001 3438 Write_rows 1 3478 table_id: ### flags: STMT_END_F +mysqld-bin.000001 3478 Xid 1 3509 COMMIT /* xid=### */ +mysqld-bin.000001 3509 Gtid 1 3557 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:16' +mysqld-bin.000001 3557 Query 1 3620 BEGIN +mysqld-bin.000001 3620 Query 1 3684 COMMIT +mysqld-bin.000001 3684 Gtid 1 3732 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:17' +mysqld-bin.000001 3732 Query 1 3795 BEGIN +mysqld-bin.000001 3795 Table_map 1 3841 table_id: ### (test1.t1) +mysqld-bin.000001 3841 Write_rows 1 3881 table_id: ### flags: STMT_END_F +mysqld-bin.000001 3881 Xid 1 3912 COMMIT /* xid=### */ +mysqld-bin.000001 3912 Gtid 1 3960 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:18' +mysqld-bin.000001 3960 Query 1 4023 BEGIN +mysqld-bin.000001 4023 Query 1 4087 COMMIT +mysqld-bin.000001 4087 Gtid 1 4135 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:19' +mysqld-bin.000001 4135 Query 1 4198 BEGIN +mysqld-bin.000001 4198 Table_map 1 4244 table_id: ### (test1.t1) +mysqld-bin.000001 4244 Write_rows 1 4284 table_id: ### flags: STMT_END_F +mysqld-bin.000001 4284 Xid 1 4315 COMMIT /* xid=### */ +mysqld-bin.000001 4315 Gtid 1 4363 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:20' +mysqld-bin.000001 4363 Query 1 4426 BEGIN +mysqld-bin.000001 4426 Query 1 4490 COMMIT +mysqld-bin.000001 4490 Gtid 1 4538 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:21' +mysqld-bin.000001 4538 Query 1 4601 BEGIN +mysqld-bin.000001 4601 Table_map 1 4647 table_id: ### (test1.t1) +mysqld-bin.000001 4647 Write_rows 1 4687 table_id: ### flags: STMT_END_F +mysqld-bin.000001 4687 Xid 1 4718 COMMIT /* xid=### */ +mysqld-bin.000001 4718 Gtid 1 4766 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:22' +mysqld-bin.000001 4766 Query 1 4829 BEGIN +mysqld-bin.000001 4829 Query 1 4893 COMMIT +mysqld-bin.000001 4893 Gtid 1 4941 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:23' +mysqld-bin.000001 4941 Query 1 5004 BEGIN +mysqld-bin.000001 5004 Table_map 1 5050 table_id: ### (test1.t1) +mysqld-bin.000001 5050 Write_rows 1 5090 table_id: ### flags: STMT_END_F +mysqld-bin.000001 5090 Xid 1 5121 COMMIT /* xid=### */ +mysqld-bin.000001 5121 Gtid 1 5169 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:24' +mysqld-bin.000001 5169 Query 1 5232 BEGIN +mysqld-bin.000001 5232 Query 1 5296 COMMIT +mysqld-bin.000001 5296 Gtid 1 5344 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:25' +mysqld-bin.000001 5344 Query 1 5407 BEGIN +mysqld-bin.000001 5407 Table_map 1 5453 table_id: ### (test1.t1) +mysqld-bin.000001 5453 Write_rows 1 5493 table_id: ### flags: STMT_END_F +mysqld-bin.000001 5493 Xid 1 5524 COMMIT /* xid=### */ +mysqld-bin.000001 5524 Gtid 1 5572 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:26' +mysqld-bin.000001 5572 Query 1 5635 BEGIN +mysqld-bin.000001 5635 Query 1 5699 COMMIT +mysqld-bin.000001 5699 Gtid 1 5747 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:27' +mysqld-bin.000001 5747 Query 1 5810 BEGIN +mysqld-bin.000001 5810 Table_map 1 5856 table_id: ### (test1.t1) +mysqld-bin.000001 5856 Write_rows 1 5896 table_id: ### flags: STMT_END_F +mysqld-bin.000001 5896 Xid 1 5927 COMMIT /* xid=### */ +mysqld-bin.000001 5927 Gtid 1 5975 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:28' +mysqld-bin.000001 5975 Query 1 6038 BEGIN +mysqld-bin.000001 6038 Query 1 6102 COMMIT +mysqld-bin.000001 6102 Gtid 1 6150 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:29' +mysqld-bin.000001 6150 Query 1 6213 BEGIN +mysqld-bin.000001 6213 Table_map 1 6259 table_id: ### (test1.t1) +mysqld-bin.000001 6259 Write_rows 1 6299 table_id: ### flags: STMT_END_F +mysqld-bin.000001 6299 Xid 1 6330 COMMIT /* xid=### */ +mysqld-bin.000001 6330 Gtid 1 6378 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:30' +mysqld-bin.000001 6378 Query 1 6441 BEGIN +mysqld-bin.000001 6441 Query 1 6505 COMMIT +USE test2; +ERROR 42000: Unknown database 'test2' +gtid_executed_equal +1 +USE test2; +ERROR 42000: Unknown database 'test2' +SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 120; +Log_name Pos Event_type Server_id End_log_pos Info +mysqld-bin.000001 120 Previous_gtids 4 151 +mysqld-bin.000001 151 Gtid 1 199 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:1' +mysqld-bin.000001 199 Query 1 294 CREATE SCHEMA test1 +mysqld-bin.000001 294 Gtid 1 342 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:2' +mysqld-bin.000001 342 Query 1 415 BEGIN +mysqld-bin.000001 415 Query 1 489 COMMIT +mysqld-bin.000001 489 Gtid 1 537 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:3' +mysqld-bin.000001 537 Query 1 655 use `test1`; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB +mysqld-bin.000001 655 Gtid 1 703 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:4' +mysqld-bin.000001 703 Query 1 776 BEGIN +mysqld-bin.000001 776 Query 1 850 COMMIT +mysqld-bin.000001 850 Gtid 1 898 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:5' +mysqld-bin.000001 898 Query 1 961 BEGIN +mysqld-bin.000001 961 Table_map 1 1007 table_id: ### (test1.t1) +mysqld-bin.000001 1007 Write_rows 1 1047 table_id: ### flags: STMT_END_F +mysqld-bin.000001 1047 Xid 1 1078 COMMIT /* xid=### */ +mysqld-bin.000001 1078 Gtid 1 1126 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:6' +mysqld-bin.000001 1126 Query 1 1189 BEGIN +mysqld-bin.000001 1189 Query 1 1253 COMMIT +mysqld-bin.000001 1253 Gtid 1 1301 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:7' +mysqld-bin.000001 1301 Query 1 1364 BEGIN +mysqld-bin.000001 1364 Table_map 1 1410 table_id: ### (test1.t1) +mysqld-bin.000001 1410 Write_rows 1 1450 table_id: ### flags: STMT_END_F +mysqld-bin.000001 1450 Xid 1 1481 COMMIT /* xid=### */ +mysqld-bin.000001 1481 Gtid 1 1529 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:8' +mysqld-bin.000001 1529 Query 1 1592 BEGIN +mysqld-bin.000001 1592 Query 1 1656 COMMIT +mysqld-bin.000001 1656 Gtid 4 1704 SET @@SESSION.GTID_NEXT= '<effective_uuid_2>:12' +mysqld-bin.000001 1704 Query 4 1772 BEGIN +mysqld-bin.000001 1772 Ignorable 4 1795 # Unrecognized ignorable event +mysqld-bin.000001 1795 Query 4 1864 COMMIT +mysqld-bin.000001 1864 Gtid 4 1912 SET @@SESSION.GTID_NEXT= '<effective_uuid_2>:13' +mysqld-bin.000001 1912 Query 4 1980 BEGIN +mysqld-bin.000001 1980 Ignorable 4 2003 # Unrecognized ignorable event +mysqld-bin.000001 2003 Query 4 2072 COMMIT +mysqld-bin.000001 2072 Gtid 1 2120 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:9' +mysqld-bin.000001 2120 Query 1 2183 BEGIN +mysqld-bin.000001 2183 Table_map 1 2229 table_id: ### (test1.t1) +mysqld-bin.000001 2229 Write_rows 1 2269 table_id: ### flags: STMT_END_F +mysqld-bin.000001 2269 Xid 1 2300 COMMIT /* xid=### */ +mysqld-bin.000001 2300 Gtid 1 2348 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:10' +mysqld-bin.000001 2348 Query 1 2411 BEGIN +mysqld-bin.000001 2411 Query 1 2475 COMMIT +mysqld-bin.000001 2475 Gtid 1 2523 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:11' +mysqld-bin.000001 2523 Query 1 2586 BEGIN +mysqld-bin.000001 2586 Table_map 1 2632 table_id: ### (test1.t1) +mysqld-bin.000001 2632 Write_rows 1 2672 table_id: ### flags: STMT_END_F +mysqld-bin.000001 2672 Xid 1 2703 COMMIT /* xid=### */ +mysqld-bin.000001 2703 Gtid 1 2751 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:12' +mysqld-bin.000001 2751 Query 1 2814 BEGIN +mysqld-bin.000001 2814 Query 1 2878 COMMIT +mysqld-bin.000001 2878 Gtid 1 2926 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:13' +mysqld-bin.000001 2926 Query 1 2989 BEGIN +mysqld-bin.000001 2989 Table_map 1 3035 table_id: ### (test1.t1) +mysqld-bin.000001 3035 Write_rows 1 3075 table_id: ### flags: STMT_END_F +mysqld-bin.000001 3075 Xid 1 3106 COMMIT /* xid=### */ +mysqld-bin.000001 3106 Gtid 1 3154 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:14' +mysqld-bin.000001 3154 Query 1 3217 BEGIN +mysqld-bin.000001 3217 Query 1 3281 COMMIT +mysqld-bin.000001 3281 Gtid 1 3329 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:15' +mysqld-bin.000001 3329 Query 1 3392 BEGIN +mysqld-bin.000001 3392 Table_map 1 3438 table_id: ### (test1.t1) +mysqld-bin.000001 3438 Write_rows 1 3478 table_id: ### flags: STMT_END_F +mysqld-bin.000001 3478 Xid 1 3509 COMMIT /* xid=### */ +mysqld-bin.000001 3509 Gtid 1 3557 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:16' +mysqld-bin.000001 3557 Query 1 3620 BEGIN +mysqld-bin.000001 3620 Query 1 3684 COMMIT +mysqld-bin.000001 3684 Gtid 1 3732 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:17' +mysqld-bin.000001 3732 Query 1 3795 BEGIN +mysqld-bin.000001 3795 Table_map 1 3841 table_id: ### (test1.t1) +mysqld-bin.000001 3841 Write_rows 1 3881 table_id: ### flags: STMT_END_F +mysqld-bin.000001 3881 Xid 1 3912 COMMIT /* xid=### */ +mysqld-bin.000001 3912 Gtid 1 3960 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:18' +mysqld-bin.000001 3960 Query 1 4023 BEGIN +mysqld-bin.000001 4023 Query 1 4087 COMMIT +mysqld-bin.000001 4087 Gtid 1 4135 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:19' +mysqld-bin.000001 4135 Query 1 4198 BEGIN +mysqld-bin.000001 4198 Table_map 1 4244 table_id: ### (test1.t1) +mysqld-bin.000001 4244 Write_rows 1 4284 table_id: ### flags: STMT_END_F +mysqld-bin.000001 4284 Xid 1 4315 COMMIT /* xid=### */ +mysqld-bin.000001 4315 Gtid 1 4363 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:20' +mysqld-bin.000001 4363 Query 1 4426 BEGIN +mysqld-bin.000001 4426 Query 1 4490 COMMIT +mysqld-bin.000001 4490 Gtid 1 4538 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:21' +mysqld-bin.000001 4538 Query 1 4601 BEGIN +mysqld-bin.000001 4601 Table_map 1 4647 table_id: ### (test1.t1) +mysqld-bin.000001 4647 Write_rows 1 4687 table_id: ### flags: STMT_END_F +mysqld-bin.000001 4687 Xid 1 4718 COMMIT /* xid=### */ +mysqld-bin.000001 4718 Gtid 1 4766 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:22' +mysqld-bin.000001 4766 Query 1 4829 BEGIN +mysqld-bin.000001 4829 Query 1 4893 COMMIT +mysqld-bin.000001 4893 Gtid 1 4941 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:23' +mysqld-bin.000001 4941 Query 1 5004 BEGIN +mysqld-bin.000001 5004 Table_map 1 5050 table_id: ### (test1.t1) +mysqld-bin.000001 5050 Write_rows 1 5090 table_id: ### flags: STMT_END_F +mysqld-bin.000001 5090 Xid 1 5121 COMMIT /* xid=### */ +mysqld-bin.000001 5121 Gtid 1 5169 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:24' +mysqld-bin.000001 5169 Query 1 5232 BEGIN +mysqld-bin.000001 5232 Query 1 5296 COMMIT +mysqld-bin.000001 5296 Gtid 1 5344 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:25' +mysqld-bin.000001 5344 Query 1 5407 BEGIN +mysqld-bin.000001 5407 Table_map 1 5453 table_id: ### (test1.t1) +mysqld-bin.000001 5453 Write_rows 1 5493 table_id: ### flags: STMT_END_F +mysqld-bin.000001 5493 Xid 1 5524 COMMIT /* xid=### */ +mysqld-bin.000001 5524 Gtid 1 5572 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:26' +mysqld-bin.000001 5572 Query 1 5635 BEGIN +mysqld-bin.000001 5635 Query 1 5699 COMMIT +mysqld-bin.000001 5699 Gtid 1 5747 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:27' +mysqld-bin.000001 5747 Query 1 5810 BEGIN +mysqld-bin.000001 5810 Table_map 1 5856 table_id: ### (test1.t1) +mysqld-bin.000001 5856 Write_rows 1 5896 table_id: ### flags: STMT_END_F +mysqld-bin.000001 5896 Xid 1 5927 COMMIT /* xid=### */ +mysqld-bin.000001 5927 Gtid 1 5975 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:28' +mysqld-bin.000001 5975 Query 1 6038 BEGIN +mysqld-bin.000001 6038 Query 1 6102 COMMIT +mysqld-bin.000001 6102 Gtid 1 6150 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:29' +mysqld-bin.000001 6150 Query 1 6213 BEGIN +mysqld-bin.000001 6213 Table_map 1 6259 table_id: ### (test1.t1) +mysqld-bin.000001 6259 Write_rows 1 6299 table_id: ### flags: STMT_END_F +mysqld-bin.000001 6299 Xid 1 6330 COMMIT /* xid=### */ +mysqld-bin.000001 6330 Gtid 1 6378 SET @@SESSION.GTID_NEXT= '<effective_uuid_1>:30' +mysqld-bin.000001 6378 Query 1 6441 BEGIN +mysqld-bin.000001 6441 Query 1 6505 COMMIT +DROP SCHEMA test1; +DROP SCHEMA test2; +STOP SLAVE; +RESET SLAVE ALL; +CALL mtr.add_suppression("GTID replication failed"); +CALL mtr.add_suppression("Slave SQL: Error in Xid_log_event: Commit could not be completed"); +CALL mtr.add_suppression("Slave SQL: Node has dropped from cluster, Error_code: 1047"); +CALL mtr.add_suppression("TO isolation failed for"); +CALL mtr.add_suppression("Slave SQL: Error 'Deadlock found when trying to get lock; try restarting transaction' on query"); +CALL mtr.add_suppression("Slave SQL: Error 'WSREP has not yet prepared node for application use' on query"); +CALL mtr.add_suppression("Slave: WSREP has not yet prepared node for application use Error_code: 1047"); diff --git a/mysql-test/suite/galera/r/galera_as_slave_nonprim.result b/mysql-test/suite/galera/r/galera_as_slave_nonprim.result index 365ea31f292..6baf930aed2 100644 --- a/mysql-test/suite/galera/r/galera_as_slave_nonprim.result +++ b/mysql-test/suite/galera/r/galera_as_slave_nonprim.result @@ -1,13 +1,28 @@ +connection node_2; +connection node_1; +connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4; +connection node_2; START SLAVE; SET SESSION wsrep_sync_wait = 0; +connection node_4; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +connection node_2; SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; +connection node_1; +connection node_4; INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +connection node_2; +connection node_1; expected_error 1 +connection node_2; SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; +connection node_1; +connection node_2; START SLAVE; +connection node_4; DROP TABLE t1; +connection node_2; STOP SLAVE; RESET SLAVE ALL; CALL mtr.add_suppression("Slave SQL: Error 'Unknown command' on query"); @@ -15,4 +30,7 @@ CALL mtr.add_suppression("Slave: Unknown command Error_code: 1047"); CALL mtr.add_suppression("Transport endpoint is not connected"); CALL mtr.add_suppression("Slave SQL: Error in Xid_log_event: Commit could not be completed, 'Deadlock found when trying to get lock; try restarting transaction', Error_code: 1213"); CALL mtr.add_suppression("Slave SQL: Node has dropped from cluster, Error_code: 1047"); +connection node_4; +SET GLOBAL wsrep_on=OFF; RESET MASTER; +SET GLOBAL wsrep_on=ON; diff --git a/mysql-test/suite/galera/r/galera_autoinc_sst_xtrabackup.result b/mysql-test/suite/galera/r/galera_autoinc_sst_xtrabackup.result index d0fac1e3d14..0d6a6ebbbc1 100644 --- a/mysql-test/suite/galera/r/galera_autoinc_sst_xtrabackup.result +++ b/mysql-test/suite/galera/r/galera_autoinc_sst_xtrabackup.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; CREATE PROCEDURE p1 () diff --git a/mysql-test/suite/galera/r/galera_bf_abort.result b/mysql-test/suite/galera/r/galera_bf_abort.result index c2e89965fce..cb4a27c82fd 100644 --- a/mysql-test/suite/galera/r/galera_bf_abort.result +++ b/mysql-test/suite/galera/r/galera_bf_abort.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(6)) ENGINE=InnoDB; connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; connection node_2; @@ -9,7 +11,7 @@ INSERT INTO t1 VALUES (1,'node_1'); connection node_2a; connection node_2; INSERT INTO t1 VALUES (2, 'node_2'); -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction wsrep_local_aborts_increment 1 DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_bf_abort_flush_for_export.result b/mysql-test/suite/galera/r/galera_bf_abort_flush_for_export.result index 7b98c807efb..1150a9fff63 100644 --- a/mysql-test/suite/galera/r/galera_bf_abort_flush_for_export.result +++ b/mysql-test/suite/galera/r/galera_bf_abort_flush_for_export.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; connection node_2; SET AUTOCOMMIT=OFF; diff --git a/mysql-test/suite/galera/r/galera_bf_abort_for_update.result b/mysql-test/suite/galera/r/galera_bf_abort_for_update.result index ec8bddb087a..7dd3053b7bb 100644 --- a/mysql-test/suite/galera/r/galera_bf_abort_for_update.result +++ b/mysql-test/suite/galera/r/galera_bf_abort_for_update.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INT) ENGINE=InnoDB; INSERT INTO t1 VALUES (1, 10); connection node_1; @@ -10,7 +12,7 @@ UPDATE t1 SET f1 = 2; connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; connection node_1; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction wsrep_local_bf_aborts_diff 1 connection node_1; @@ -23,7 +25,7 @@ UPDATE t1 SET f2 = 20; connection node_1a; connection node_1; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction wsrep_local_bf_aborts_diff 1 DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_bf_abort_ftwrl.result b/mysql-test/suite/galera/r/galera_bf_abort_ftwrl.result index ae1ca6d2157..43ca6089d78 100644 --- a/mysql-test/suite/galera/r/galera_bf_abort_ftwrl.result +++ b/mysql-test/suite/galera/r/galera_bf_abort_ftwrl.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; connection node_2; SET AUTOCOMMIT=OFF; diff --git a/mysql-test/suite/galera/r/galera_bf_abort_get_lock.result b/mysql-test/suite/galera/r/galera_bf_abort_get_lock.result index 8c6c7b7d7a4..0ef2a1a72c6 100644 --- a/mysql-test/suite/galera/r/galera_bf_abort_get_lock.result +++ b/mysql-test/suite/galera/r/galera_bf_abort_get_lock.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; connection node_2a; SELECT GET_LOCK("foo", 1000); @@ -10,7 +12,7 @@ SELECT GET_LOCK("foo", 1000);; connection node_1; INSERT INTO t1 VALUES (1); connection node_2; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction wsrep_local_aborts_increment 1 DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_bf_abort_group_commit.result b/mysql-test/suite/galera/r/galera_bf_abort_group_commit.result new file mode 100644 index 00000000000..52d44c3d510 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_bf_abort_group_commit.result @@ -0,0 +1,685 @@ +SET SESSION wsrep_sync_wait = 0; +galera_sr_bf_abort_at_commit = 0 +after_replicate_sync +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; +f1 +1 +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,after_replicate_sync'; +INSERT INTO t1 VALUES (3); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync'; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +ROLLBACK; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +local_monitor_master_enter_sync +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; +f1 +1 +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync'; +INSERT INTO t1 VALUES (3); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync'; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +ROLLBACK; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +apply_monitor_master_enter_sync +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; +f1 +1 +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_master_enter_sync'; +INSERT INTO t1 VALUES (3); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_master_enter_sync'; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +ROLLBACK; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +commit_monitor_master_enter_sync +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; +f1 +1 +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync'; +INSERT INTO t1 VALUES (3); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync'; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +ROLLBACK; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +galera_sr_bf_abort_at_commit = 1 +after_replicate_sync +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; +f1 +1 +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,after_replicate_sync'; +COMMIT; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync'; +ROLLBACK; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +local_monitor_master_enter_sync +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; +f1 +1 +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync'; +COMMIT; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync'; +ROLLBACK; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +apply_monitor_master_enter_sync +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; +f1 +1 +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_master_enter_sync'; +COMMIT; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_master_enter_sync'; +ROLLBACK; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +commit_monitor_master_enter_sync +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; +f1 +1 +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync'; +COMMIT; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync'; +ROLLBACK; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +galera_sr_bf_abort_at_commit = 1 +after_replicate_sync +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 0; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; +f1 +1 +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,after_replicate_sync'; +COMMIT; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync'; +ROLLBACK; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +local_monitor_master_enter_sync +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 0; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; +f1 +1 +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync'; +COMMIT; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync'; +ROLLBACK; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +apply_monitor_master_enter_sync +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 0; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; +f1 +1 +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_master_enter_sync'; +COMMIT; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_master_enter_sync'; +ROLLBACK; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +commit_monitor_master_enter_sync +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 0; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; +f1 +1 +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync'; +COMMIT; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync'; +ROLLBACK; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +CALL mtr.add_suppression("WSREP: fragment replication failed: 1"); diff --git a/mysql-test/suite/galera/r/galera_bf_abort_lock_table.result b/mysql-test/suite/galera/r/galera_bf_abort_lock_table.result index 81b5816ddbe..e7882e43b6a 100644 --- a/mysql-test/suite/galera/r/galera_bf_abort_lock_table.result +++ b/mysql-test/suite/galera/r/galera_bf_abort_lock_table.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; connection node_2; SET AUTOCOMMIT=OFF; diff --git a/mysql-test/suite/galera/r/galera_bf_abort_shutdown.result b/mysql-test/suite/galera/r/galera_bf_abort_shutdown.result new file mode 100644 index 00000000000..6f67d9ce4cc --- /dev/null +++ b/mysql-test/suite/galera/r/galera_bf_abort_shutdown.result @@ -0,0 +1,9 @@ +connection node_2; +connection node_1; +CREATE TABLE t1 (f1 INT PRIMARY KEY); +connection node_2; +SET DEBUG_SYNC = 'wsrep_before_replication WAIT_FOR continue'; +INSERT INTO t1 VALUES (1); +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_1; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_bf_abort_sleep.result b/mysql-test/suite/galera/r/galera_bf_abort_sleep.result index 9cd6abad5a1..00d6600d264 100644 --- a/mysql-test/suite/galera/r/galera_bf_abort_sleep.result +++ b/mysql-test/suite/galera/r/galera_bf_abort_sleep.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; connection node_2; SET AUTOCOMMIT=OFF; @@ -6,7 +8,7 @@ SELECT SLEEP(1000);; connection node_1; INSERT INTO t1 VALUES (1); connection node_2; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction wsrep_local_aborts_increment 1 DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_bf_lock_wait.result b/mysql-test/suite/galera/r/galera_bf_lock_wait.result index 7ec524da888..f893848a72d 100644 --- a/mysql-test/suite/galera/r/galera_bf_lock_wait.result +++ b/mysql-test/suite/galera/r/galera_bf_lock_wait.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 ENGINE=InnoDB select 1 as a, 1 as b union select 2, 2; ALTER TABLE t1 add primary key(a); CREATE PROCEDURE p1() diff --git a/mysql-test/suite/galera/r/galera_binlog_cache_size.result b/mysql-test/suite/galera/r/galera_binlog_cache_size.result index 6aac74ab5f0..c5a09074537 100644 --- a/mysql-test/suite/galera/r/galera_binlog_cache_size.result +++ b/mysql-test/suite/galera/r/galera_binlog_cache_size.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 VARCHAR(767)) ENGINE=InnoDB; CREATE TABLE ten (f1 INTEGER); INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); diff --git a/mysql-test/suite/galera/r/galera_binlog_checksum.result b/mysql-test/suite/galera/r/galera_binlog_checksum.result index 7303aa61122..3ef7cf5c41e 100644 --- a/mysql-test/suite/galera/r/galera_binlog_checksum.result +++ b/mysql-test/suite/galera/r/galera_binlog_checksum.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; diff --git a/mysql-test/suite/galera/r/galera_binlog_event_max_size_max.result b/mysql-test/suite/galera/r/galera_binlog_event_max_size_max.result index 46582ff5c4b..b513c491bb0 100644 --- a/mysql-test/suite/galera/r/galera_binlog_event_max_size_max.result +++ b/mysql-test/suite/galera/r/galera_binlog_event_max_size_max.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE ten (f1 INTEGER); INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); CREATE TABLE t1 (f1 VARCHAR(1000)); diff --git a/mysql-test/suite/galera/r/galera_binlog_event_max_size_min.result b/mysql-test/suite/galera/r/galera_binlog_event_max_size_min.result index 7b88af5d5af..6c2279bece0 100644 --- a/mysql-test/suite/galera/r/galera_binlog_event_max_size_min.result +++ b/mysql-test/suite/galera/r/galera_binlog_event_max_size_min.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 VARCHAR(1000)); INSERT INTO t1 VALUES (REPEAT('x', 1000)); connection node_2; diff --git a/mysql-test/suite/galera/r/galera_binlog_row_image.result b/mysql-test/suite/galera/r/galera_binlog_row_image.result index d54db61105e..20e6bd9fab8 100644 --- a/mysql-test/suite/galera/r/galera_binlog_row_image.result +++ b/mysql-test/suite/galera/r/galera_binlog_row_image.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; SET SESSION binlog_row_image=minimal; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; diff --git a/mysql-test/suite/galera/r/galera_create_function.result b/mysql-test/suite/galera/r/galera_create_function.result index 9118c2864f3..85fa85d81f1 100644 --- a/mysql-test/suite/galera/r/galera_create_function.result +++ b/mysql-test/suite/galera/r/galera_create_function.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE USER 'user1'; CREATE diff --git a/mysql-test/suite/galera/r/galera_create_procedure.result b/mysql-test/suite/galera/r/galera_create_procedure.result index 98dc4a856dc..24a0bd66b39 100644 --- a/mysql-test/suite/galera/r/galera_create_procedure.result +++ b/mysql-test/suite/galera/r/galera_create_procedure.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE USER 'user1'; CREATE TABLE t1 (f1 INTEGER); diff --git a/mysql-test/suite/galera/r/galera_create_table_as_select.result b/mysql-test/suite/galera/r/galera_create_table_as_select.result new file mode 100644 index 00000000000..6f65ee99f0a --- /dev/null +++ b/mysql-test/suite/galera/r/galera_create_table_as_select.result @@ -0,0 +1,103 @@ +connection node_2; +connection node_1; +connection node_1; +SET SESSION default_storage_engine=InnoDB; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 AS SELECT * FROM t2; +ERROR 42S01: Table 't1' already exists +DROP TABLE t1,t2; +CREATE TABLE t1 AS SELECT * FROM t2; +ERROR 42S02: Table 'test.t2' doesn't exist +CREATE TABLE t1 AS SELECT 1 FROM DUAL; +connection node_2; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +connection node_1; +DROP TABLE t1; +connection node_1; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 AS SELECT * FROM t2; +connection node_2; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +connection node_1; +DROP TABLE t1,t2; +CREATE TABLE t2 (f1 INTEGER) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1),(2),(3),(4),(5); +CREATE TABLE t1 AS SELECT * FROM t2; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +connection node_2; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +connection node_1; +DROP TABLE t1,t2; +connection node_1; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3),(4),(5); +CREATE TABLE t1 AS SELECT MAX(f1) AS f1 FROM t2; +connection node_2; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT f1 = 5 FROM t1; +f1 = 5 +1 +connection node_1; +DROP TABLE t1,t2; +connection node_1; +CREATE PROCEDURE sp1 () +BEGIN +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3),(4),(5); +CREATE TABLE t1 AS SELECT * FROM t2; +END| +CALL sp1(); +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +connection node_2; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +connection node_1; +DROP TABLE t1, t2; +DROP PROCEDURE sp1; +connection node_1; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3),(4),(5); +PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT * FROM t2'; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; +DROP TABLE t1, t2; +connection node_1; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3),(4),(5); +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +LOCK TABLE t2 WRITE; +connection node_1; +CREATE TABLE t1 AS SELECT * FROM t2;; +connection node_2; +SELECT COUNT(*) = 5 FROM t2; +COUNT(*) = 5 +1 +CREATE TABLE t1 AS SELECT * FROM t2; +connection node_1a; +UNLOCK TABLES; +connection node_1; +Got one of the listed errors +DROP TABLE t1, t2; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3),(4),(5); +CREATE TEMPORARY TABLE t1 AS SELECT * FROM t2; +connection node_2; +SELECT * FROM t1; +ERROR 42S02: Table 'test.t1' doesn't exist +CALL mtr.add_suppression("Slave SQL: Error 'Unknown table 'test.t1'' on query"); +connection node_1; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/galera/r/galera_create_table_like.result b/mysql-test/suite/galera/r/galera_create_table_like.result index 131ac311bca..82543331ad5 100644 --- a/mysql-test/suite/galera/r/galera_create_table_like.result +++ b/mysql-test/suite/galera/r/galera_create_table_like.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE SCHEMA schema1; CREATE SCHEMA schema2; USE schema1; diff --git a/mysql-test/suite/galera/r/galera_create_trigger.result b/mysql-test/suite/galera/r/galera_create_trigger.result index d07a007543e..56b35150d87 100644 --- a/mysql-test/suite/galera/r/galera_create_trigger.result +++ b/mysql-test/suite/galera/r/galera_create_trigger.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE definer_root (f1 INTEGER, trigger_user VARCHAR(100)) ENGINE=InnoDB; CREATE TABLE definer_user (f1 INTEGER, trigger_user VARCHAR(100)) ENGINE=InnoDB; CREATE TABLE definer_current_user (f1 INTEGER, trigger_user VARCHAR(100)) ENGINE=InnoDB; diff --git a/mysql-test/suite/galera/r/galera_ddl_multiline.result b/mysql-test/suite/galera/r/galera_ddl_multiline.result index 339a91125eb..9e70731a62b 100644 --- a/mysql-test/suite/galera/r/galera_ddl_multiline.result +++ b/mysql-test/suite/galera/r/galera_ddl_multiline.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; diff --git a/mysql-test/suite/galera/r/galera_defaults.result b/mysql-test/suite/galera/r/galera_defaults.result index 5c5fdabf432..381b334908e 100644 --- a/mysql-test/suite/galera/r/galera_defaults.result +++ b/mysql-test/suite/galera/r/galera_defaults.result @@ -1,6 +1,12 @@ -SELECT COUNT(*) = 43 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%'; -COUNT(*) = 43 -0 +connection node_2; +connection node_1; +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '4.dev(r3810)' +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '4.dev(r3810)' +SELECT COUNT(*) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%'; +COUNT(*) +48 SELECT VARIABLE_NAME, VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%' @@ -31,6 +37,7 @@ WSREP_DRUPAL_282555_WORKAROUND OFF WSREP_FORCED_BINLOG_FORMAT NONE WSREP_GTID_DOMAIN_ID 0 WSREP_GTID_MODE OFF +WSREP_IGNORE_APPLY_ERRORS 7 WSREP_LOAD_DATA_SPLITTING ON WSREP_LOG_CONFLICTS OFF WSREP_MAX_WS_ROWS 0 @@ -47,17 +54,20 @@ WSREP_RETRY_AUTOCOMMIT 1 WSREP_SLAVE_FK_CHECKS ON WSREP_SLAVE_THREADS 1 WSREP_SLAVE_UK_CHECKS OFF +WSREP_SR_STORE table WSREP_SST_AUTH WSREP_SST_DONOR WSREP_SST_DONOR_REJECTS_QUERIES OFF WSREP_SST_METHOD rsync WSREP_SYNC_WAIT 15 -<BASE_DIR>; <BASE_HOST>; <BASE_PORT>; cert.log_conflicts = no; debug = no; evs.auto_evict = 0; evs.causal_keepalive_period = PT1S; evs.debug_log_mask = 0x1; evs.delay_margin = PT1S; evs.delayed_keep_period = PT30S; evs.inactive_check_period = PT0.5S; evs.inactive_timeout = PT30S; evs.info_log_mask = 0; evs.install_timeout = PT15S; evs.join_retrans_period = PT1S; evs.keepalive_period = PT1S; evs.max_install_timeouts = 3; evs.send_window = 4; evs.stats_report_period = PT1M; evs.suspect_timeout = PT10S; evs.use_aggregate = true; evs.user_send_window = 2; evs.version = 0; evs.view_forget_timeout = P1D; <GCACHE_DIR>; gcache.keep_pages_size = 0; gcache.mem_size = 0; <GCACHE_NAME>; gcache.page_size = 128M; gcache.recover = no; gcache.size = 10M; gcomm.thread_prio = ; gcs.fc_debug = 0; gcs.fc_factor = 1.0; gcs.fc_limit = 16; gcs.fc_master_slave = no; gcs.max_packet_size = 64500; gcs.max_throttle = 0.25; <GCS_RECV_Q_HARD_LIMIT>; gcs.recv_q_soft_limit = 0.25; gcs.sync_donor = no; <GMCAST_LISTEN_ADDR>; gmcast.mcast_addr = ; gmcast.mcast_ttl = 1; gmcast.peer_timeout = PT3S; gmcast.segment = 0; gmcast.time_wait = PT5S; gmcast.version = 0; <IST_RECV_ADDR>; pc.announce_timeout = PT3S; pc.checksum = false; pc.ignore_quorum = false; pc.ignore_sb = false; pc.linger = PT20S; pc.npvo = false; pc.recovery = true; pc.version = 0; pc.wait_prim = true; pc.wait_prim_timeout = PT30S; pc.weight = 1; protonet.backend = asio; protonet.version = 0; repl.causal_read_timeout = PT90S; repl.commit_order = 3; repl.key_format = FLAT8; repl.max_ws_size = 2147483647; <REPL_PROTO_MAX>;socket.checksum = 2; socket.recv_buf_size = 212992; +WSREP_TRX_FRAGMENT_SIZE 0 +WSREP_TRX_FRAGMENT_UNIT bytes +<BASE_DIR>; <BASE_HOST>; <BASE_PORT>; cert.log_conflicts = no; debug = no; evs.auto_evict = 0; evs.causal_keepalive_period = PT1S; evs.debug_log_mask = 0x1; evs.delay_margin = PT1S; evs.delayed_keep_period = PT30S; evs.inactive_check_period = PT0.5S; evs.inactive_timeout = PT30S; evs.info_log_mask = 0; evs.install_timeout = PT15S; evs.join_retrans_period = PT1S; evs.keepalive_period = PT1S; evs.max_install_timeouts = 3; evs.send_window = 4; evs.stats_report_period = PT1M; evs.suspect_timeout = PT10S; evs.use_aggregate = true; evs.user_send_window = 2; evs.version = 1; evs.view_forget_timeout = P1D; <GCACHE_DIR>; gcache.keep_pages_size = 0; gcache.mem_size = 0; <GCACHE_NAME>; gcache.page_size = 128M; gcache.recover = yes; gcache.size = 10M; gcomm.thread_prio = ; gcs.fc_debug = 0; gcs.fc_factor = 1.0; gcs.fc_limit = 16; gcs.fc_master_slave = no; gcs.max_packet_size = 64500; gcs.max_throttle = 0.25; <GCS_RECV_Q_HARD_LIMIT>; gcs.recv_q_soft_limit = 0.25; gcs.sync_donor = no; <GMCAST_LISTEN_ADDR>; gmcast.mcast_addr = ; gmcast.mcast_ttl = 1; gmcast.peer_timeout = PT3S; gmcast.segment = 0; gmcast.time_wait = PT5S; gmcast.version = 0; <IST_RECV_ADDR>; pc.announce_timeout = PT3S; pc.checksum = false; pc.ignore_quorum = false; pc.ignore_sb = false; pc.linger = PT20S; pc.npvo = false; pc.recovery = true; pc.version = 0; pc.wait_prim = true; pc.wait_prim_timeout = PT30S; pc.weight = 1; protonet.backend = asio; protonet.version = 0; repl.causal_read_timeout = PT90S; repl.commit_order = 3; repl.key_format = FLAT8; repl.max_ws_size = 2147483647; <REPL_PROTO_MAX>; socket.checksum = 2; socket.recv_buf_size = 212992; SELECT COUNT(*) FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE 'wsrep_%' AND VARIABLE_NAME != 'wsrep_debug_sync_waiters'; COUNT(*) -58 +63 SELECT VARIABLE_NAME FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE 'wsrep_%' AND VARIABLE_NAME != 'wsrep_debug_sync_waiters' @@ -70,10 +80,12 @@ WSREP_CAUSAL_READS WSREP_CERT_DEPS_DISTANCE WSREP_CERT_INDEX_SIZE WSREP_CERT_INTERVAL +WSREP_CLUSTER_CAPABILITIES WSREP_CLUSTER_CONF_ID WSREP_CLUSTER_SIZE WSREP_CLUSTER_STATE_UUID WSREP_CLUSTER_STATUS +WSREP_CLUSTER_WEIGHT WSREP_COMMIT_OOOE WSREP_COMMIT_OOOL WSREP_COMMIT_WINDOW @@ -107,7 +119,10 @@ WSREP_LOCAL_SEND_QUEUE_MIN WSREP_LOCAL_STATE WSREP_LOCAL_STATE_COMMENT WSREP_LOCAL_STATE_UUID +WSREP_OPEN_CONNECTIONS +WSREP_OPEN_TRANSACTIONS WSREP_PROTOCOL_VERSION +WSREP_PROVIDER_CAPABILITIES WSREP_PROVIDER_NAME WSREP_PROVIDER_VENDOR WSREP_PROVIDER_VERSION diff --git a/mysql-test/suite/galera/r/galera_delete_limit.result b/mysql-test/suite/galera/r/galera_delete_limit.result index f6fb2e56346..9898bfcf169 100644 --- a/mysql-test/suite/galera/r/galera_delete_limit.result +++ b/mysql-test/suite/galera/r/galera_delete_limit.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE ten (f1 INTEGER) Engine=InnoDB; INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); diff --git a/mysql-test/suite/galera/r/galera_desync_overlapped.result b/mysql-test/suite/galera/r/galera_desync_overlapped.result index f9920e7f7ad..e3f40d444ee 100644 --- a/mysql-test/suite/galera/r/galera_desync_overlapped.result +++ b/mysql-test/suite/galera/r/galera_desync_overlapped.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE ten (f1 INTEGER); INSERT INTO ten VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); diff --git a/mysql-test/suite/galera/r/galera_drop_multi.result b/mysql-test/suite/galera/r/galera_drop_multi.result index 7793ef93b90..1ff8afe3219 100644 --- a/mysql-test/suite/galera/r/galera_drop_multi.result +++ b/mysql-test/suite/galera/r/galera_drop_multi.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM; CREATE TEMPORARY TABLE t2 (f1 INTEGER) ENGINE=MyISAM; CREATE TABLE t3 (f1 INTEGER) ENGINE=InnoDB; diff --git a/mysql-test/suite/galera/r/galera_enum.result b/mysql-test/suite/galera/r/galera_enum.result index dcf31aa5948..92b72fc69c0 100644 --- a/mysql-test/suite/galera/r/galera_enum.result +++ b/mysql-test/suite/galera/r/galera_enum.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (f1 ENUM('', 'one', 'two'), KEY (f1)) ENGINE=InnoDB; INSERT INTO t1 VALUES (''); @@ -38,7 +40,7 @@ connection node_1; COMMIT; connection node_2; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction connection node_1; SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 'three'; COUNT(*) = 1 diff --git a/mysql-test/suite/galera/r/galera_events.result b/mysql-test/suite/galera/r/galera_events.result index f01627aba70..791b0be729d 100644 --- a/mysql-test/suite/galera/r/galera_events.result +++ b/mysql-test/suite/galera/r/galera_events.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE EVENT event1 ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR DO SELECT 1; connection node_2; diff --git a/mysql-test/suite/galera/r/galera_fk_cascade_delete.result b/mysql-test/suite/galera/r/galera_fk_cascade_delete.result index 73375ae55c5..291d641db88 100644 --- a/mysql-test/suite/galera/r/galera_fk_cascade_delete.result +++ b/mysql-test/suite/galera/r/galera_fk_cascade_delete.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE grandparent ( id INT NOT NULL PRIMARY KEY ) ENGINE=InnoDB; diff --git a/mysql-test/suite/galera/r/galera_fk_cascade_update.result b/mysql-test/suite/galera/r/galera_fk_cascade_update.result index 5fe8b532473..5294826a8f9 100644 --- a/mysql-test/suite/galera/r/galera_fk_cascade_update.result +++ b/mysql-test/suite/galera/r/galera_fk_cascade_update.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE grandparent ( id INT NOT NULL PRIMARY KEY ) ENGINE=InnoDB; diff --git a/mysql-test/suite/galera/r/galera_fk_conflict.result b/mysql-test/suite/galera/r/galera_fk_conflict.result index a08aa30a82e..f9f151abce4 100644 --- a/mysql-test/suite/galera/r/galera_fk_conflict.result +++ b/mysql-test/suite/galera/r/galera_fk_conflict.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE parent ( id INT PRIMARY KEY, KEY (id) @@ -22,6 +24,6 @@ connection node_1; COMMIT; connection node_2; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction DROP TABLE child; DROP TABLE parent; diff --git a/mysql-test/suite/galera/r/galera_fk_mismatch.result b/mysql-test/suite/galera/r/galera_fk_mismatch.result index bdc60c9e099..a030b1214c5 100644 --- a/mysql-test/suite/galera/r/galera_fk_mismatch.result +++ b/mysql-test/suite/galera/r/galera_fk_mismatch.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE parent ( id1 INT, id2 INT, diff --git a/mysql-test/suite/galera/r/galera_fk_multicolumn.result b/mysql-test/suite/galera/r/galera_fk_multicolumn.result index f5b6aa23692..b626d963af8 100644 --- a/mysql-test/suite/galera/r/galera_fk_multicolumn.result +++ b/mysql-test/suite/galera/r/galera_fk_multicolumn.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t0 ( f1 INT PRIMARY KEY, f2 INT UNIQUE diff --git a/mysql-test/suite/galera/r/galera_fk_multitable.result b/mysql-test/suite/galera/r/galera_fk_multitable.result index 04ff7adc3e9..83e1491ab34 100644 --- a/mysql-test/suite/galera/r/galera_fk_multitable.result +++ b/mysql-test/suite/galera/r/galera_fk_multitable.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t0 ( f0 INT PRIMARY KEY ); diff --git a/mysql-test/suite/galera/r/galera_fk_no_pk.result b/mysql-test/suite/galera/r/galera_fk_no_pk.result index e7b5f0b2b64..622e63dbb8f 100644 --- a/mysql-test/suite/galera/r/galera_fk_no_pk.result +++ b/mysql-test/suite/galera/r/galera_fk_no_pk.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE parent ( id INT, KEY (id) diff --git a/mysql-test/suite/galera/r/galera_fk_selfreferential.result b/mysql-test/suite/galera/r/galera_fk_selfreferential.result index 3b4dbf2a8e9..9a64521e7b8 100644 --- a/mysql-test/suite/galera/r/galera_fk_selfreferential.result +++ b/mysql-test/suite/galera/r/galera_fk_selfreferential.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 ( f1 INT NOT NULL PRIMARY KEY, f2 INT, diff --git a/mysql-test/suite/galera/r/galera_fk_setnull.result b/mysql-test/suite/galera/r/galera_fk_setnull.result index d4f20fe60a3..afb3fc3b9b8 100644 --- a/mysql-test/suite/galera/r/galera_fk_setnull.result +++ b/mysql-test/suite/galera/r/galera_fk_setnull.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE parent ( id INT NOT NULL, PRIMARY KEY (id) diff --git a/mysql-test/suite/galera/r/galera_flush_local.result b/mysql-test/suite/galera/r/galera_flush_local.result index a8e798a693d..123b8098727 100644 --- a/mysql-test/suite/galera/r/galera_flush_local.result +++ b/mysql-test/suite/galera/r/galera_flush_local.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; DROP TABLE IF EXISTS t1, t2, x1, x2; connection node_1; CREATE TABLE t1 (f1 INTEGER); diff --git a/mysql-test/suite/galera/r/galera_forced_binlog_format.result b/mysql-test/suite/galera/r/galera_forced_binlog_format.result index b94e6530886..a94ac0c112d 100644 --- a/mysql-test/suite/galera/r/galera_forced_binlog_format.result +++ b/mysql-test/suite/galera/r/galera_forced_binlog_format.result @@ -1,5 +1,10 @@ +connection node_2; connection node_1; +connection node_1; +SEt GLOBAL wsrep_on=OFF; RESET MASTER; +SEt GLOBAL wsrep_on=ON; +FLUSH BINARY LOGS; SET SESSION binlog_format = 'STATEMENT'; Warnings: Warning 1105 MariaDB Galera and flashback do not support binlog format: STATEMENT @@ -13,18 +18,7 @@ SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 256; Log_name Pos Event_type Server_id End_log_pos Info mysqld-bin.000001 <Pos> Gtid_list 1 <End_log_pos> [] mysqld-bin.000001 <Pos> Binlog_checkpoint 1 <End_log_pos> mysqld-bin.000001 -mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> GTID 0-1-1 -mysqld-bin.000001 <Pos> Query 1 <End_log_pos> use `test`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB -mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> BEGIN GTID 0-1-2 -mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (1) -mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1) -mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F -mysqld-bin.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */ -mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> BEGIN GTID 0-1-3 -mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (2) -mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1) -mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F -mysqld-bin.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */ +mysqld-bin.000001 <Pos> Rotate 1 <End_log_pos> mysqld-bin.000002;pos=4 DROP TABLE t1; # # MDEV-9401: wsrep_forced_binlog_format with binlog causes crash @@ -43,6 +37,4 @@ GRANT ALL PRIVILEGES ON `testdb_9401`.`t1` TO 'dummy'@'localhost' REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost; DROP USER dummy@localhost; DROP DATABASE testdb_9401; -disconnect node_2; -disconnect node_1; # End of tests diff --git a/mysql-test/suite/galera/r/galera_ftwrl.result b/mysql-test/suite/galera/r/galera_ftwrl.result index 0565781c051..eae8028a7f4 100644 --- a/mysql-test/suite/galera/r/galera_ftwrl.result +++ b/mysql-test/suite/galera/r/galera_ftwrl.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; connection node_2; SET GLOBAL wsrep_provider_options = "repl.causal_read_timeout=PT1S"; diff --git a/mysql-test/suite/galera/r/galera_ftwrl_drain.result b/mysql-test/suite/galera/r/galera_ftwrl_drain.result index 751811b88fd..1e1dc65da3e 100644 --- a/mysql-test/suite/galera/r/galera_ftwrl_drain.result +++ b/mysql-test/suite/galera/r/galera_ftwrl_drain.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; connection node_2; diff --git a/mysql-test/suite/galera/r/galera_fulltext.result b/mysql-test/suite/galera/r/galera_fulltext.result index 18e3bff40fc..a22296278fa 100644 --- a/mysql-test/suite/galera/r/galera_fulltext.result +++ b/mysql-test/suite/galera/r/galera_fulltext.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); connection node_1; diff --git a/mysql-test/suite/galera/r/galera_gcache_recover_full_gcache.result b/mysql-test/suite/galera/r/galera_gcache_recover_full_gcache.result index 30ee5772411..45c426dfdf1 100644 --- a/mysql-test/suite/galera/r/galera_gcache_recover_full_gcache.result +++ b/mysql-test/suite/galera/r/galera_gcache_recover_full_gcache.result @@ -15,5 +15,5 @@ Using --wsrep-start-position when starting mysqld ... include/diff_servers.inc [servers=1 2] DROP TABLE t1; CALL mtr.add_suppression("Skipped GCache ring buffer recovery"); -include/assert_grep.inc [IST first seqno 2 not found from cache, falling back to SST] +include/assert_grep.inc [IST first seqno [24] not found from cache, falling back to SST] CALL mtr.add_suppression("Skipped GCache ring buffer recovery"); diff --git a/mysql-test/suite/galera/r/galera_gcs_fc_limit.result b/mysql-test/suite/galera/r/galera_gcs_fc_limit.result index 464a8b7ea97..83eaa0fb7aa 100644 --- a/mysql-test/suite/galera/r/galera_gcs_fc_limit.result +++ b/mysql-test/suite/galera/r/galera_gcs_fc_limit.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; diff --git a/mysql-test/suite/galera/r/galera_gcs_max_packet_size.result b/mysql-test/suite/galera/r/galera_gcs_max_packet_size.result index ce74f3db433..b97be5733ff 100644 --- a/mysql-test/suite/galera/r/galera_gcs_max_packet_size.result +++ b/mysql-test/suite/galera/r/galera_gcs_max_packet_size.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE ten (f1 INTEGER); INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); CREATE TABLE t1 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 INTEGER) ENGINE=InnoDB; diff --git a/mysql-test/suite/galera/r/galera_gra_log.result b/mysql-test/suite/galera/r/galera_gra_log.result index 777eda42046..33853188965 100644 --- a/mysql-test/suite/galera/r/galera_gra_log.result +++ b/mysql-test/suite/galera/r/galera_gra_log.result @@ -1,4 +1,6 @@ connection node_2; +connection node_1; +connection node_2; SET SESSION wsrep_on=OFF; CREATE TABLE t1 (f1 INTEGER); connection node_1; diff --git a/mysql-test/suite/galera/r/galera_gtid.result b/mysql-test/suite/galera/r/galera_gtid.result index acc5eae9876..f27e2590898 100644 --- a/mysql-test/suite/galera/r/galera_gtid.result +++ b/mysql-test/suite/galera/r/galera_gtid.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INT PRIMARY KEY); INSERT INTO t1 VALUES (1); connection node_2; diff --git a/mysql-test/suite/galera/r/galera_gtid_slave.result b/mysql-test/suite/galera/r/galera_gtid_slave.result index f8ca6322d22..4f207659316 100644 --- a/mysql-test/suite/galera/r/galera_gtid_slave.result +++ b/mysql-test/suite/galera/r/galera_gtid_slave.result @@ -1,5 +1,7 @@ connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; connection node_2; +connection node_1; +connection node_2; START SLAVE; connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; @@ -25,13 +27,18 @@ SELECT @@global.gtid_binlog_state; 1-1-4,2-2-2,2-3-3 connection node_1; DROP TABLE t1,t2; +SET GLOBAL wsrep_on=OFF; +reset master; +SET GLOBAL wsrep_on=ON; connection node_2; connection node_3; connection node_2; STOP SLAVE; RESET SLAVE ALL; +SET GLOBAL wsrep_on=OFF; reset master; +SET GLOBAL wsrep_on=ON; connection node_3; +SET GLOBAL wsrep_on=OFF; reset master; -connection node_1; -reset master; +SET GLOBAL wsrep_on=ON; diff --git a/mysql-test/suite/galera/r/galera_gtid_slave_sst_rsync.result b/mysql-test/suite/galera/r/galera_gtid_slave_sst_rsync.result index cdf330643c2..e8b4a4665c5 100644 --- a/mysql-test/suite/galera/r/galera_gtid_slave_sst_rsync.result +++ b/mysql-test/suite/galera/r/galera_gtid_slave_sst_rsync.result @@ -1,38 +1,40 @@ -connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_2; +connection node_1; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; #Connection 2 connection node_2; START SLAVE; -#Connection 1 -connection node_1; +#Connection 3 +connection node_3; CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 int unique) ENGINE=InnoDB; INSERT INTO t2 VALUES(1,11); INSERT INTO t2 VALUES(2,22); INSERT INTO t2 VALUES(3,33); SELECT @@global.gtid_binlog_state; @@global.gtid_binlog_state -1-1-4 +2-1-4 include/save_master_gtid.inc #Connection 2 connection node_2; include/sync_with_master_gtid.inc SELECT @@global.gtid_binlog_state; @@global.gtid_binlog_state -1-1-4 +2-1-4 INSERT INTO t2 VALUES(4,44); INSERT INTO t2 VALUES(5,55); INSERT INTO t2 VALUES(6,66); SELECT @@global.gtid_binlog_state; @@global.gtid_binlog_state -1-1-4,2-2-3 -#Connection 3 -connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +0-2-3,2-1-4 +#Connection 1 +connection node_1; INSERT INTO t2 VALUES(7,77); INSERT INTO t2 VALUES(8,88); SELECT @@global.gtid_binlog_state; @@global.gtid_binlog_state -1-1-4,2-2-3,2-3-5 -#Connection 1 -connection node_1; +1-3-2,2-1-4,2-2-7 +#Connection 3 +connection node_3; CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; SET AUTOCOMMIT=OFF; START TRANSACTION; @@ -48,76 +50,78 @@ START TRANSACTION; INSERT INTO t1 VALUES ('node2_committed_before'); INSERT INTO t1 VALUES ('node2_committed_before'); COMMIT; -#Connection 3 -connection node_3; +#Connection 1 +connection node_1; +connection node_1; connection node_2; -connection node_3; -Shutting down server ... #Connection 2 connection node_2; +Shutting down server ... +#Connection 1 +connection node_1; SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 VALUES ('node1_committed_during'); INSERT INTO t1 VALUES ('node1_committed_during'); COMMIT; -#Connection 3 -connection node_3; +#Connection 2 +connection node_2; Starting server ... SET AUTOCOMMIT=OFF; START TRANSACTION; -INSERT INTO t1 VALUES ('node3_committed_after'); -INSERT INTO t1 VALUES ('node3_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); COMMIT; -#Connection 2 -connection node_2; +#Connection 1 +connection node_1; Select * from t1 order by f1; f1 node1_committed_before node1_committed_before node1_committed_during node1_committed_during +node2_committed_after +node2_committed_after node2_committed_before node2_committed_before -node3_committed_after -node3_committed_after -#Connection 3 -connection node_3; +#Connection 2 +connection node_2; Select * from t1 order by f1; f1 node1_committed_before node1_committed_before node1_committed_during node1_committed_during +node2_committed_after +node2_committed_after node2_committed_before node2_committed_before -node3_committed_after -node3_committed_after +#Connection 1 +connection node_1; +SELECT @@global.gtid_binlog_state; +@@global.gtid_binlog_state +1-3-3,2-1-6,2-2-9 #Connection 2 connection node_2; SELECT @@global.gtid_binlog_state; @@global.gtid_binlog_state -1-1-6,2-2-7,2-3-8 +0-3-7,0-2-8,2-1-6 #Connection 3 connection node_3; -SELECT @@global.gtid_binlog_state; -@@global.gtid_binlog_state -1-1-6,2-2-7,2-3-8 -#Connection 1 -connection node_1; SET AUTOCOMMIT=ON; #Connection 2 connection node_2; SET AUTOCOMMIT=ON; -#Connection 3 -connection node_3; +#Connection 1 +connection node_1; SET AUTOCOMMIT=ON; #Connection 2 connection node_2; STOP slave; INSERT INTO t1 VALUES ('node2_slave_stoped'); -#Connection 1 -connection node_1; -INSERT INTO t1 VALUES ('node1_normal_entry'); +#Connection 3 +connection node_3; +INSERT INTO t1 VALUES ('node3_normal_entry'); include/save_master_gtid.inc #Connection 2 connection node_2; @@ -130,30 +134,34 @@ count(*) 12 SELECT @@global.gtid_binlog_state; @@global.gtid_binlog_state -1-1-7,2-3-8,2-2-11 -#Connection 3 -connection node_3; +0-3-7,0-2-11,2-1-7 +#Connection 1 +connection node_1; SELECT count(*) from t1; count(*) 12 SELECT @@global.gtid_binlog_state; @@global.gtid_binlog_state -1-1-7,2-3-8,2-2-11 -#Connection 1 -connection node_1; +1-3-3,2-1-7,2-2-12 +#Connection 3 +connection node_3; DROP TABLE t2,t1; #Connection 2 connection node_2; -#Connection 3 -connection node_3; +#Connection 1 +connection node_1; #Connection 2 connection node_2; STOP SLAVE; RESET SLAVE ALL; +set global wsrep_on=OFF; reset master; -#Connection 3 -connection node_3; -reset master; +set global wsrep_on=ON; #Connection 1 connection node_1; +set global wsrep_on=OFF; +reset master; +set global wsrep_on=ON; +#Connection 3 +connection node_3; reset master; diff --git a/mysql-test/suite/galera/r/galera_insert_ignore.result b/mysql-test/suite/galera/r/galera_insert_ignore.result index 7057affaa0e..417524240e7 100644 --- a/mysql-test/suite/galera/r/galera_insert_ignore.result +++ b/mysql-test/suite/galera/r/galera_insert_ignore.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; SET GLOBAL wsrep_sync_wait = 15; connection node_2; SET GLOBAL wsrep_sync_wait = 15; diff --git a/mysql-test/suite/galera/r/galera_insert_multi.result b/mysql-test/suite/galera/r/galera_insert_multi.result index 913dd42403a..d7a4f01873e 100644 --- a/mysql-test/suite/galera/r/galera_insert_multi.result +++ b/mysql-test/suite/galera/r/galera_insert_multi.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1),(2); @@ -51,7 +53,7 @@ connection node_1; COMMIT; connection node_2; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction ROLLBACK; INSERT INTO t1 VALUES (1), (2); ERROR 23000: Duplicate entry '1' for key 'PRIMARY' diff --git a/mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result b/mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result index 5421b234ee1..cad00aaee48 100644 --- a/mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result +++ b/mysql-test/suite/galera/r/galera_ist_innodb_flush_logs.result @@ -1,4 +1,7 @@ +connection node_2; +connection node_1; Performing State Transfer on a server that has been killed and restarted +connection node_1; CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; SET AUTOCOMMIT=OFF; START TRANSACTION; @@ -8,6 +11,7 @@ INSERT INTO t1 VALUES ('node1_committed_before'); INSERT INTO t1 VALUES ('node1_committed_before'); INSERT INTO t1 VALUES ('node1_committed_before'); COMMIT; +connection node_2; SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 VALUES ('node2_committed_before'); @@ -17,6 +21,7 @@ INSERT INTO t1 VALUES ('node2_committed_before'); INSERT INTO t1 VALUES ('node2_committed_before'); COMMIT; Killing server ... +connection node_1; SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 VALUES ('node1_committed_during'); @@ -31,6 +36,7 @@ INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +connect node_1a_galera_st_kill_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1; SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); @@ -38,6 +44,7 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +connection node_2; Performing --wsrep-recover ... Starting server ... Using --wsrep-start-position when starting mysqld ... @@ -49,6 +56,7 @@ INSERT INTO t1 VALUES ('node2_committed_after'); INSERT INTO t1 VALUES ('node2_committed_after'); INSERT INTO t1 VALUES ('node2_committed_after'); COMMIT; +connection node_1; INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); @@ -63,6 +71,7 @@ INSERT INTO t1 VALUES ('node1_committed_after'); INSERT INTO t1 VALUES ('node1_committed_after'); INSERT INTO t1 VALUES ('node1_committed_after'); COMMIT; +connection node_1a_galera_st_kill_slave; INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); @@ -77,6 +86,7 @@ COUNT(*) = 0 1 COMMIT; SET AUTOCOMMIT=ON; +connection node_1; SELECT COUNT(*) = 35 FROM t1; COUNT(*) = 35 1 @@ -88,6 +98,7 @@ COMMIT; SET AUTOCOMMIT=ON; Performing State Transfer on a server that has been killed and restarted while a DDL was in progress on it +connection node_1; CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; SET AUTOCOMMIT=OFF; START TRANSACTION; @@ -96,6 +107,7 @@ INSERT INTO t1 VALUES ('node1_committed_before'); INSERT INTO t1 VALUES ('node1_committed_before'); INSERT INTO t1 VALUES ('node1_committed_before'); INSERT INTO t1 VALUES ('node1_committed_before'); +connection node_2; START TRANSACTION; INSERT INTO t1 VALUES ('node2_committed_before'); INSERT INTO t1 VALUES ('node2_committed_before'); @@ -103,10 +115,13 @@ INSERT INTO t1 VALUES ('node2_committed_before'); INSERT INTO t1 VALUES ('node2_committed_before'); INSERT INTO t1 VALUES ('node2_committed_before'); COMMIT; -SET GLOBAL debug = 'd,sync.alter_opened_table'; +SET GLOBAL debug_dbug = 'd,sync.alter_opened_table'; +connection node_1; ALTER TABLE t1 ADD COLUMN f2 INTEGER; +connection node_2; SET wsrep_sync_wait = 0; Killing server ... +connection node_1; SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 (f1) VALUES ('node1_committed_during'); @@ -121,6 +136,7 @@ INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1; SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); @@ -128,7 +144,9 @@ INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +connection node_2; Performing --wsrep-recover ... +connection node_2; Starting server ... Using --wsrep-start-position when starting mysqld ... SET AUTOCOMMIT=OFF; @@ -139,6 +157,7 @@ INSERT INTO t1 (f1) VALUES ('node2_committed_after'); INSERT INTO t1 (f1) VALUES ('node2_committed_after'); INSERT INTO t1 (f1) VALUES ('node2_committed_after'); COMMIT; +connection node_1; INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); @@ -153,6 +172,7 @@ INSERT INTO t1 (f1) VALUES ('node1_committed_after'); INSERT INTO t1 (f1) VALUES ('node1_committed_after'); INSERT INTO t1 (f1) VALUES ('node1_committed_after'); COMMIT; +connection node_1a_galera_st_kill_slave_ddl; INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); @@ -170,6 +190,7 @@ COUNT(*) = 0 1 COMMIT; SET AUTOCOMMIT=ON; +connection node_1; SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; COUNT(*) = 2 1 @@ -182,3 +203,4 @@ COUNT(*) = 0 DROP TABLE t1; COMMIT; SET AUTOCOMMIT=ON; +SET GLOBAL debug_dbug = $debug_orig; diff --git a/mysql-test/suite/galera/r/galera_ist_progress.result b/mysql-test/suite/galera/r/galera_ist_progress.result index ed36a217624..4795fc1224b 100644 --- a/mysql-test/suite/galera/r/galera_ist_progress.result +++ b/mysql-test/suite/galera/r/galera_ist_progress.result @@ -1,4 +1,9 @@ connection node_2; +<<<<<<< HEAD +connection node_1; +connection node_2; +======= +>>>>>>> 10.3 SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1'; connection node_1; connection node_2; diff --git a/mysql-test/suite/galera/r/galera_ist_recv_bind.result b/mysql-test/suite/galera/r/galera_ist_recv_bind.result index ffc751d8672..be72aa60ab0 100644 --- a/mysql-test/suite/galera/r/galera_ist_recv_bind.result +++ b/mysql-test/suite/galera/r/galera_ist_recv_bind.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; SELECT @@wsrep_provider_options LIKE '%ist.recv_bind = 127.0.0.1%'; @@wsrep_provider_options LIKE '%ist.recv_bind = 127.0.0.1%' diff --git a/mysql-test/suite/galera/r/galera_ist_restart_joiner.result b/mysql-test/suite/galera/r/galera_ist_restart_joiner.result index c81cecfae1c..80d2c90642b 100644 --- a/mysql-test/suite/galera/r/galera_ist_restart_joiner.result +++ b/mysql-test/suite/galera/r/galera_ist_restart_joiner.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; connection node_2; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)); @@ -13,7 +15,6 @@ Loading wsrep_provider ... SET SESSION wsrep_on=OFF; SET SESSION wsrep_on=ON; connection node_1; -connection node_1; UPDATE t1 SET f2 = 'd' WHERE f1 > 3; connection node_2; connection node_1; diff --git a/mysql-test/suite/galera/r/galera_ist_rsync.result b/mysql-test/suite/galera/r/galera_ist_rsync.result index 9c0d78d96e9..f5464e4044a 100644 --- a/mysql-test/suite/galera/r/galera_ist_rsync.result +++ b/mysql-test/suite/galera/r/galera_ist_rsync.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; connection node_2; Performing State Transfer on a server that has been temporarily disconnected diff --git a/mysql-test/suite/galera/r/galera_ist_xtrabackup-v2.result b/mysql-test/suite/galera/r/galera_ist_xtrabackup-v2.result index 175e7443a4d..579370fb25c 100644 --- a/mysql-test/suite/galera/r/galera_ist_xtrabackup-v2.result +++ b/mysql-test/suite/galera/r/galera_ist_xtrabackup-v2.result @@ -1,4 +1,7 @@ +connection node_2; +connection node_1; Performing State Transfer on a server that has been temporarily disconnected +connection node_1; CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; SET AUTOCOMMIT=OFF; START TRANSACTION; @@ -8,6 +11,7 @@ INSERT INTO t1 VALUES ('node1_committed_before'); INSERT INTO t1 VALUES ('node1_committed_before'); INSERT INTO t1 VALUES ('node1_committed_before'); COMMIT; +connection node_2; SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 VALUES ('node2_committed_before'); @@ -18,6 +22,7 @@ INSERT INTO t1 VALUES ('node2_committed_before'); COMMIT; Unloading wsrep provider ... SET GLOBAL wsrep_provider = 'none'; +connection node_1; SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 VALUES ('node1_committed_during'); @@ -32,6 +37,7 @@ INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +connect node_1a_galera_st_disconnect_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1; SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); @@ -39,6 +45,7 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +connection node_2; Loading wsrep provider ... SET AUTOCOMMIT=OFF; START TRANSACTION; @@ -48,6 +55,7 @@ INSERT INTO t1 VALUES ('node2_committed_after'); INSERT INTO t1 VALUES ('node2_committed_after'); INSERT INTO t1 VALUES ('node2_committed_after'); COMMIT; +connection node_1; INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); @@ -62,6 +70,7 @@ INSERT INTO t1 VALUES ('node1_committed_after'); INSERT INTO t1 VALUES ('node1_committed_after'); INSERT INTO t1 VALUES ('node1_committed_after'); COMMIT; +connection node_1a_galera_st_disconnect_slave; INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); @@ -76,6 +85,7 @@ COUNT(*) = 0 1 COMMIT; SET AUTOCOMMIT=ON; +connection node_1; SELECT COUNT(*) = 35 FROM t1; COUNT(*) = 35 1 @@ -86,6 +96,7 @@ DROP TABLE t1; COMMIT; SET AUTOCOMMIT=ON; Performing State Transfer on a server that has been shut down cleanly and restarted +connection node_1; CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; SET AUTOCOMMIT=OFF; START TRANSACTION; @@ -95,6 +106,7 @@ INSERT INTO t1 VALUES ('node1_committed_before'); INSERT INTO t1 VALUES ('node1_committed_before'); INSERT INTO t1 VALUES ('node1_committed_before'); COMMIT; +connection node_2; SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 VALUES ('node2_committed_before'); @@ -104,6 +116,7 @@ INSERT INTO t1 VALUES ('node2_committed_before'); INSERT INTO t1 VALUES ('node2_committed_before'); COMMIT; Shutting down server ... +connection node_1; SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 VALUES ('node1_committed_during'); @@ -118,6 +131,7 @@ INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +connect node_1a_galera_st_shutdown_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1; SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); @@ -125,6 +139,7 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +connection node_2; Starting server ... SET AUTOCOMMIT=OFF; START TRANSACTION; @@ -134,6 +149,7 @@ INSERT INTO t1 VALUES ('node2_committed_after'); INSERT INTO t1 VALUES ('node2_committed_after'); INSERT INTO t1 VALUES ('node2_committed_after'); COMMIT; +connection node_1; INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); @@ -148,6 +164,7 @@ INSERT INTO t1 VALUES ('node1_committed_after'); INSERT INTO t1 VALUES ('node1_committed_after'); INSERT INTO t1 VALUES ('node1_committed_after'); COMMIT; +connection node_1a_galera_st_shutdown_slave; INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); @@ -162,6 +179,7 @@ COUNT(*) = 0 1 COMMIT; SET AUTOCOMMIT=ON; +connection node_1; SELECT COUNT(*) = 35 FROM t1; COUNT(*) = 35 1 @@ -172,6 +190,7 @@ DROP TABLE t1; COMMIT; SET AUTOCOMMIT=ON; Performing State Transfer on a server that has been killed and restarted +connection node_1; CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; SET AUTOCOMMIT=OFF; START TRANSACTION; @@ -181,6 +200,7 @@ INSERT INTO t1 VALUES ('node1_committed_before'); INSERT INTO t1 VALUES ('node1_committed_before'); INSERT INTO t1 VALUES ('node1_committed_before'); COMMIT; +connection node_2; SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 VALUES ('node2_committed_before'); @@ -190,6 +210,7 @@ INSERT INTO t1 VALUES ('node2_committed_before'); INSERT INTO t1 VALUES ('node2_committed_before'); COMMIT; Killing server ... +connection node_1; SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 VALUES ('node1_committed_during'); @@ -204,6 +225,7 @@ INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); +connect node_1a_galera_st_kill_slave, 127.0.0.1, root, , test, $NODE_MYPORT_1; SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); @@ -211,6 +233,7 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); +connection node_2; Performing --wsrep-recover ... Starting server ... Using --wsrep-start-position when starting mysqld ... @@ -222,6 +245,7 @@ INSERT INTO t1 VALUES ('node2_committed_after'); INSERT INTO t1 VALUES ('node2_committed_after'); INSERT INTO t1 VALUES ('node2_committed_after'); COMMIT; +connection node_1; INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); INSERT INTO t1 VALUES ('node1_to_be_committed_after'); @@ -236,6 +260,7 @@ INSERT INTO t1 VALUES ('node1_committed_after'); INSERT INTO t1 VALUES ('node1_committed_after'); INSERT INTO t1 VALUES ('node1_committed_after'); COMMIT; +connection node_1a_galera_st_kill_slave; INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); @@ -250,6 +275,7 @@ COUNT(*) = 0 1 COMMIT; SET AUTOCOMMIT=ON; +connection node_1; SELECT COUNT(*) = 35 FROM t1; COUNT(*) = 35 1 @@ -261,6 +287,7 @@ COMMIT; SET AUTOCOMMIT=ON; Performing State Transfer on a server that has been killed and restarted while a DDL was in progress on it +connection node_1; CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; SET AUTOCOMMIT=OFF; START TRANSACTION; @@ -269,6 +296,7 @@ INSERT INTO t1 VALUES ('node1_committed_before'); INSERT INTO t1 VALUES ('node1_committed_before'); INSERT INTO t1 VALUES ('node1_committed_before'); INSERT INTO t1 VALUES ('node1_committed_before'); +connection node_2; START TRANSACTION; INSERT INTO t1 VALUES ('node2_committed_before'); INSERT INTO t1 VALUES ('node2_committed_before'); @@ -276,10 +304,13 @@ INSERT INTO t1 VALUES ('node2_committed_before'); INSERT INTO t1 VALUES ('node2_committed_before'); INSERT INTO t1 VALUES ('node2_committed_before'); COMMIT; -SET GLOBAL debug = 'd,sync.alter_opened_table'; +SET GLOBAL debug_dbug = 'd,sync.alter_opened_table'; +connection node_1; ALTER TABLE t1 ADD COLUMN f2 INTEGER; +connection node_2; SET wsrep_sync_wait = 0; Killing server ... +connection node_1; SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 (f1) VALUES ('node1_committed_during'); @@ -294,6 +325,7 @@ INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1; SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); @@ -301,7 +333,9 @@ INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +connection node_2; Performing --wsrep-recover ... +connection node_2; Starting server ... Using --wsrep-start-position when starting mysqld ... SET AUTOCOMMIT=OFF; @@ -312,6 +346,7 @@ INSERT INTO t1 (f1) VALUES ('node2_committed_after'); INSERT INTO t1 (f1) VALUES ('node2_committed_after'); INSERT INTO t1 (f1) VALUES ('node2_committed_after'); COMMIT; +connection node_1; INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); @@ -326,6 +361,7 @@ INSERT INTO t1 (f1) VALUES ('node1_committed_after'); INSERT INTO t1 (f1) VALUES ('node1_committed_after'); INSERT INTO t1 (f1) VALUES ('node1_committed_after'); COMMIT; +connection node_1a_galera_st_kill_slave_ddl; INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); @@ -343,6 +379,7 @@ COUNT(*) = 0 1 COMMIT; SET AUTOCOMMIT=ON; +connection node_1; SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; COUNT(*) = 2 1 @@ -355,3 +392,4 @@ COUNT(*) = 0 DROP TABLE t1; COMMIT; SET AUTOCOMMIT=ON; +SET GLOBAL debug_dbug = $debug_orig; diff --git a/mysql-test/suite/galera/r/galera_kill_ddl.result b/mysql-test/suite/galera/r/galera_kill_ddl.result index aac316dffe3..33df5889d44 100644 --- a/mysql-test/suite/galera/r/galera_kill_ddl.result +++ b/mysql-test/suite/galera/r/galera_kill_ddl.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; diff --git a/mysql-test/suite/galera/r/galera_kill_largechanges.result b/mysql-test/suite/galera/r/galera_kill_largechanges.result index d04bd548949..dcdab11de4b 100644 --- a/mysql-test/suite/galera/r/galera_kill_largechanges.result +++ b/mysql-test/suite/galera/r/galera_kill_largechanges.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; CREATE TABLE ten (f1 INTEGER); diff --git a/mysql-test/suite/galera/r/galera_kill_smallchanges.result b/mysql-test/suite/galera/r/galera_kill_smallchanges.result index bcd7d6fd15d..45626b8f9a9 100644 --- a/mysql-test/suite/galera/r/galera_kill_smallchanges.result +++ b/mysql-test/suite/galera/r/galera_kill_smallchanges.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; diff --git a/mysql-test/suite/galera/r/galera_lock_table.result b/mysql-test/suite/galera/r/galera_lock_table.result index ce529deb22c..c3df1749ada 100644 --- a/mysql-test/suite/galera/r/galera_lock_table.result +++ b/mysql-test/suite/galera/r/galera_lock_table.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB; connection node_2; diff --git a/mysql-test/suite/galera/r/galera_log_bin.result b/mysql-test/suite/galera/r/galera_log_bin.result index a6f0ef12be1..12e5e59a426 100644 --- a/mysql-test/suite/galera/r/galera_log_bin.result +++ b/mysql-test/suite/galera/r/galera_log_bin.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); CREATE TABLE t2 (id INT) ENGINE=InnoDB; @@ -66,4 +68,6 @@ mysqld-bin.000003 # Query # # use `test`; ALTER TABLE t1 ADD COLUMN f2 INTEGER DROP TABLE t1; DROP TABLE t2; connection node_1; +SET GLOBAL wsrep_on=OFF; RESET MASTER; +SET GLOBAL wsrep_on=ON; diff --git a/mysql-test/suite/galera/r/galera_log_output_csv.result b/mysql-test/suite/galera/r/galera_log_output_csv.result index 5cb61b36332..efe8c73c986 100644 --- a/mysql-test/suite/galera/r/galera_log_output_csv.result +++ b/mysql-test/suite/galera/r/galera_log_output_csv.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); SELECT COUNT(*) > 0 FROM mysql.general_log; diff --git a/mysql-test/suite/galera/r/galera_many_columns.result b/mysql-test/suite/galera/r/galera_many_columns.result index db8a8f5ec9d..64e97f11fa7 100644 --- a/mysql-test/suite/galera/r/galera_many_columns.result +++ b/mysql-test/suite/galera/r/galera_many_columns.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; INSERT INTO t1 (f1) VALUES (DEFAULT); connection node_2; SELECT f1 = 'ABC', f1017 = 'ABC' FROM t1; @@ -19,7 +21,7 @@ UPDATE t1 SET f2 = 'CDE' WHERE f1 = 'XYZ' AND f1017 = 'XYZ'; COMMIT; connection node_1; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction ROLLBACK; connection node_2; ROLLBACK; diff --git a/mysql-test/suite/galera/r/galera_many_indexes.result b/mysql-test/suite/galera/r/galera_many_indexes.result index 5691eef4c00..9a1ede485eb 100644 --- a/mysql-test/suite/galera/r/galera_many_indexes.result +++ b/mysql-test/suite/galera/r/galera_many_indexes.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 VARCHAR(767) PRIMARY KEY) ENGINE=InnoDB; CREATE UNIQUE INDEX i63 ON t1(f1); CREATE UNIQUE INDEX i62 ON t1(f1); @@ -129,5 +131,5 @@ connection node_1; COMMIT; connection node_2; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_many_rows.result b/mysql-test/suite/galera/r/galera_many_rows.result index b06925fea60..28613c20779 100644 --- a/mysql-test/suite/galera/r/galera_many_rows.result +++ b/mysql-test/suite/galera/r/galera_many_rows.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; SET SESSION innodb_lock_wait_timeout=600; SET SESSION lock_wait_timeout=600; @@ -35,6 +37,6 @@ connection node_1; COMMIT; connection node_2; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction DROP TABLE t1; DROP TABLE ten; diff --git a/mysql-test/suite/galera/r/galera_many_tables_nopk.result b/mysql-test/suite/galera/r/galera_many_tables_nopk.result index 573ce758a13..2a226defcc7 100644 --- a/mysql-test/suite/galera/r/galera_many_tables_nopk.result +++ b/mysql-test/suite/galera/r/galera_many_tables_nopk.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; SET AUTOCOMMIT=OFF; START TRANSACTION; @@ -18,6 +20,6 @@ connection node_1; COMMIT; connection node_2; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction DROP SCHEMA test; CREATE SCHEMA test; diff --git a/mysql-test/suite/galera/r/galera_many_tables_pk.result b/mysql-test/suite/galera/r/galera_many_tables_pk.result index 67624d5edb0..2700df8ebe4 100644 --- a/mysql-test/suite/galera/r/galera_many_tables_pk.result +++ b/mysql-test/suite/galera/r/galera_many_tables_pk.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; connection node_2; SELECT COUNT(*) = 100 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME LIKE 't%'; @@ -23,7 +25,7 @@ connection node_1; COMMIT; connection node_2; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction include/diff_servers.inc [servers=1 2] DROP SCHEMA test; CREATE SCHEMA test; diff --git a/mysql-test/suite/galera/r/galera_mdev_10812.result b/mysql-test/suite/galera/r/galera_mdev_10812.result index de0a08a3794..16eacc6beab 100644 --- a/mysql-test/suite/galera/r/galera_mdev_10812.result +++ b/mysql-test/suite/galera/r/galera_mdev_10812.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; # # MDEV-10812: On COM_STMT_CLOSE/COM_QUIT, when wsrep_conflict_state # is ABORTED, it causes wrong response to be sent to the client diff --git a/mysql-test/suite/galera/r/galera_mdev_13787.result b/mysql-test/suite/galera/r/galera_mdev_13787.result index b1caec0283c..4d0770918c0 100644 --- a/mysql-test/suite/galera/r/galera_mdev_13787.result +++ b/mysql-test/suite/galera/r/galera_mdev_13787.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; create table t(a int); insert into t select 1; diff --git a/mysql-test/suite/galera/r/galera_mdl_race.result b/mysql-test/suite/galera/r/galera_mdl_race.result index 048b2c46a67..e05c1493322 100644 --- a/mysql-test/suite/galera/r/galera_mdl_race.result +++ b/mysql-test/suite/galera/r/galera_mdl_race.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)); CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)); INSERT INTO t1 VALUES (1, 'a'); @@ -28,7 +30,7 @@ SET DEBUG_SYNC = "now SIGNAL signal.wsrep_before_mdl_wait"; SET DEBUG_SYNC = "now SIGNAL signal.wsrep_after_BF_victim_lock"; UNLOCK TABLES; connection node_1; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'a'; COUNT(*) = 1 1 diff --git a/mysql-test/suite/galera/r/galera_multi_database.result b/mysql-test/suite/galera/r/galera_multi_database.result index f6242de663b..a9d58d5d0e2 100644 --- a/mysql-test/suite/galera/r/galera_multi_database.result +++ b/mysql-test/suite/galera/r/galera_multi_database.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE DATABASE d1; CREATE TABLE d1.t1(f1 INTEGER) ENGINE=InnoDB; CREATE DATABASE d2; diff --git a/mysql-test/suite/galera/r/galera_myisam_autocommit.result b/mysql-test/suite/galera/r/galera_myisam_autocommit.result index e9578a261e6..6213e8f6380 100644 --- a/mysql-test/suite/galera/r/galera_myisam_autocommit.result +++ b/mysql-test/suite/galera/r/galera_myisam_autocommit.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM; INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (2), (3); diff --git a/mysql-test/suite/galera/r/galera_myisam_transactions.result b/mysql-test/suite/galera/r/galera_myisam_transactions.result index 25796c309d1..091c5ffb6f6 100644 --- a/mysql-test/suite/galera/r/galera_myisam_transactions.result +++ b/mysql-test/suite/galera/r/galera_myisam_transactions.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; CREATE TABLE t2 (f1 INTEGER) ENGINE=MyISAM; CREATE TABLE t3 (f1 INTEGER) ENGINE=MyISAM; diff --git a/mysql-test/suite/galera/r/galera_nopk_bit.result b/mysql-test/suite/galera/r/galera_nopk_bit.result index 21da039df09..97ded793c08 100644 --- a/mysql-test/suite/galera/r/galera_nopk_bit.result +++ b/mysql-test/suite/galera/r/galera_nopk_bit.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 BIT) ENGINE=InnoDB; INSERT INTO t1 VALUES (NULL),(0),(b'1'); connection node_2; @@ -28,6 +30,6 @@ connection node_1; COMMIT; connection node_2; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction DROP TABLE t1; DROP TABLE t2; diff --git a/mysql-test/suite/galera/r/galera_nopk_blob.result b/mysql-test/suite/galera/r/galera_nopk_blob.result index 53e04f72d1e..6a3cee516c9 100644 --- a/mysql-test/suite/galera/r/galera_nopk_blob.result +++ b/mysql-test/suite/galera/r/galera_nopk_blob.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 BLOB) ENGINE=InnoDB; INSERT INTO t1 VALUES (NULL),('abc'); connection node_2; @@ -28,6 +30,6 @@ connection node_1; COMMIT; connection node_2; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction DROP TABLE t1; DROP TABLE t2; diff --git a/mysql-test/suite/galera/r/galera_nopk_large_varchar.result b/mysql-test/suite/galera/r/galera_nopk_large_varchar.result index a83cf7f2d91..6d29306996b 100644 --- a/mysql-test/suite/galera/r/galera_nopk_large_varchar.result +++ b/mysql-test/suite/galera/r/galera_nopk_large_varchar.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 VARCHAR(8000)) ENGINE=InnoDB; INSERT INTO t1 VALUES (NULL),(CONCAT(REPEAT('x', 7999), 'a')); connection node_2; @@ -31,6 +33,6 @@ connection node_1; COMMIT; connection node_2; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction DROP TABLE t1; DROP TABLE t2; diff --git a/mysql-test/suite/galera/r/galera_nopk_unicode.result b/mysql-test/suite/galera/r/galera_nopk_unicode.result index b2a8bb63df9..587ba9285da 100644 --- a/mysql-test/suite/galera/r/galera_nopk_unicode.result +++ b/mysql-test/suite/galera/r/galera_nopk_unicode.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 ( f1 VARCHAR(255), KEY (f1) @@ -19,7 +21,7 @@ connection node_1; COMMIT; connection node_2; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction SELECT f1 = 'текст2' FROM t1; f1 = 'текст2' 1 diff --git a/mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result b/mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result index ab56a8a2aa6..eac84cb77d2 100644 --- a/mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result +++ b/mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB; connection node_2; @@ -8,10 +10,10 @@ INSERT INTO t1 VALUES (1); INSERT INTO t2 VALUES (1); connection node_2a; SET SESSION wsrep_sync_wait=0; -SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%applied write set%'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%committing%'; COUNT(*) = 1 1 -SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Waiting for table metadata lock'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%Waiting for table metadata lock%'; COUNT(*) = 1 1 SELECT COUNT(*) = 0 FROM t1; diff --git a/mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result b/mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result index 827b2aa9dac..f52839b5c8b 100644 --- a/mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result +++ b/mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE ten (f1 INTEGER); INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); @@ -22,7 +24,7 @@ COUNT(DISTINCT f1) SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE NOT LIKE 'InnoDB%'; COUNT(*) -3 +4 connection default; DROP TABLE t1; DROP TABLE ten; diff --git a/mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result b/mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result index c8c07221cb1..62b092962bc 100644 --- a/mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result +++ b/mysql-test/suite/galera/r/galera_parallel_autoinc_manytrx.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE ten (f1 INTEGER); INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); diff --git a/mysql-test/suite/galera/r/galera_parallel_simple.result b/mysql-test/suite/galera/r/galera_parallel_simple.result index 3f657a0479e..d95abefdc24 100644 --- a/mysql-test/suite/galera/r/galera_parallel_simple.result +++ b/mysql-test/suite/galera/r/galera_parallel_simple.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (id INT) ENGINE=InnoDB; CREATE TABLE t2 (id INT) ENGINE=InnoDB; connection node_2; diff --git a/mysql-test/suite/galera/r/galera_pk_bigint_signed.result b/mysql-test/suite/galera/r/galera_pk_bigint_signed.result index 807ab62c548..0b538778204 100644 --- a/mysql-test/suite/galera/r/galera_pk_bigint_signed.result +++ b/mysql-test/suite/galera/r/galera_pk_bigint_signed.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 BIGINT SIGNED PRIMARY KEY, f2 VARCHAR(5)) ENGINE=InnoDB; INSERT INTO t1 VALUES (-9223372036854775808, 'min'), @@ -27,6 +29,6 @@ COMMIT; SET AUTOCOMMIT=ON; connection node_2; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction SET AUTOCOMMIT=ON; DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_pk_bigint_unsigned.result b/mysql-test/suite/galera/r/galera_pk_bigint_unsigned.result index c94b7e2314a..9442f79cd14 100644 --- a/mysql-test/suite/galera/r/galera_pk_bigint_unsigned.result +++ b/mysql-test/suite/galera/r/galera_pk_bigint_unsigned.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 BIGINT UNSIGNED PRIMARY KEY, f2 VARCHAR(5)) ENGINE=InnoDB; INSERT INTO t1 VALUES (18446744073709551615, 'max') @@ -24,6 +26,6 @@ COMMIT; SET AUTOCOMMIT=ON; connection node_2; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction SET AUTOCOMMIT=ON; DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_prepared_statement.result b/mysql-test/suite/galera/r/galera_prepared_statement.result index d32d412ff46..943f7d0b263 100644 --- a/mysql-test/suite/galera/r/galera_prepared_statement.result +++ b/mysql-test/suite/galera/r/galera_prepared_statement.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 CHAR(5)) ENGINE=InnoDB; CREATE TABLE t2 (f1 CHAR(5)) ENGINE=InnoDB; CREATE TABLE t3 (f1 CHAR(5)) ENGINE=InnoDB; diff --git a/mysql-test/suite/galera/r/galera_query_cache.result b/mysql-test/suite/galera/r/galera_query_cache.result index e64c9438646..8f5bc4b6f37 100644 --- a/mysql-test/suite/galera/r/galera_query_cache.result +++ b/mysql-test/suite/galera/r/galera_query_cache.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; diff --git a/mysql-test/suite/galera/r/galera_query_cache_sync_wait.result b/mysql-test/suite/galera/r/galera_query_cache_sync_wait.result index 8c9cece9097..4ee910f9169 100644 --- a/mysql-test/suite/galera/r/galera_query_cache_sync_wait.result +++ b/mysql-test/suite/galera/r/galera_query_cache_sync_wait.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; diff --git a/mysql-test/suite/galera/r/galera_read_only.result b/mysql-test/suite/galera/r/galera_read_only.result index 4c2523f8691..fe8b45fa596 100644 --- a/mysql-test/suite/galera/r/galera_read_only.result +++ b/mysql-test/suite/galera/r/galera_read_only.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; connection node_2; SET GLOBAL read_only=TRUE; diff --git a/mysql-test/suite/galera/r/galera_repl_key_format_flat16.result b/mysql-test/suite/galera/r/galera_repl_key_format_flat16.result index 2470f59c497..3d421216f93 100644 --- a/mysql-test/suite/galera/r/galera_repl_key_format_flat16.result +++ b/mysql-test/suite/galera/r/galera_repl_key_format_flat16.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; SET GLOBAL wsrep_provider_options = 'repl.key_format=FLAT16'; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; diff --git a/mysql-test/suite/galera/r/galera_repl_max_ws_size.result b/mysql-test/suite/galera/r/galera_repl_max_ws_size.result index da24a741351..0528df7b9f6 100644 --- a/mysql-test/suite/galera/r/galera_repl_max_ws_size.result +++ b/mysql-test/suite/galera/r/galera_repl_max_ws_size.result @@ -1,8 +1,10 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (f1 VARCHAR(512)) ENGINE=InnoDB; SET GLOBAL wsrep_provider_options = 'repl.max_ws_size=512'; INSERT INTO t1 VALUES (REPEAT('a', 512)); -ERROR HY000: Got error 90 "Message too long" during COMMIT +ERROR HY000: Got error 5 "Input/output error" during COMMIT SELECT COUNT(*) = 0 FROM t1; COUNT(*) = 0 1 diff --git a/mysql-test/suite/galera/r/galera_restart_nochanges.result b/mysql-test/suite/galera/r/galera_restart_nochanges.result index b35ae50e2fb..09f8d9a586b 100644 --- a/mysql-test/suite/galera/r/galera_restart_nochanges.result +++ b/mysql-test/suite/galera/r/galera_restart_nochanges.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; connection node_2; connection node_1; diff --git a/mysql-test/suite/galera/r/galera_restart_on_unknown_option.result b/mysql-test/suite/galera/r/galera_restart_on_unknown_option.result index ba6f30fcf30..6e672c2d444 100644 --- a/mysql-test/suite/galera/r/galera_restart_on_unknown_option.result +++ b/mysql-test/suite/galera/r/galera_restart_on_unknown_option.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CALL mtr.add_suppression("Aborting"); CALL mtr.add_suppression("unknown option '--galera-unknown-option'"); connection node_1; diff --git a/mysql-test/suite/galera/r/galera_rsu_add_pk.result b/mysql-test/suite/galera/r/galera_rsu_add_pk.result index 4c79da154e2..9b068ba30d1 100644 --- a/mysql-test/suite/galera/r/galera_rsu_add_pk.result +++ b/mysql-test/suite/galera/r/galera_rsu_add_pk.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE ten (f1 INTEGER); INSERT INTO ten VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); diff --git a/mysql-test/suite/galera/r/galera_rsu_drop_pk.result b/mysql-test/suite/galera/r/galera_rsu_drop_pk.result index f64649ef4e2..7d731955691 100644 --- a/mysql-test/suite/galera/r/galera_rsu_drop_pk.result +++ b/mysql-test/suite/galera/r/galera_rsu_drop_pk.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE ten (f1 INTEGER); INSERT INTO ten VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); diff --git a/mysql-test/suite/galera/r/galera_rsu_error.result b/mysql-test/suite/galera/r/galera_rsu_error.result index 5c16e34b492..f78e8fa544c 100644 --- a/mysql-test/suite/galera/r/galera_rsu_error.result +++ b/mysql-test/suite/galera/r/galera_rsu_error.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; INSERT INTO t1 VALUES (1), (1); connection node_2; diff --git a/mysql-test/suite/galera/r/galera_rsu_simple.result b/mysql-test/suite/galera/r/galera_rsu_simple.result index d0ddcfb4d64..d75ef094065 100644 --- a/mysql-test/suite/galera/r/galera_rsu_simple.result +++ b/mysql-test/suite/galera/r/galera_rsu_simple.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; connection node_2; SET SESSION wsrep_OSU_method = "RSU"; diff --git a/mysql-test/suite/galera/r/galera_rsu_wsrep_desync.result b/mysql-test/suite/galera/r/galera_rsu_wsrep_desync.result index a103e810588..310611a0e49 100644 --- a/mysql-test/suite/galera/r/galera_rsu_wsrep_desync.result +++ b/mysql-test/suite/galera/r/galera_rsu_wsrep_desync.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; SET GLOBAL wsrep_desync=1; diff --git a/mysql-test/suite/galera/r/galera_sbr.result b/mysql-test/suite/galera/r/galera_sbr.result index 0bdaeef5b8a..c5fdecece0e 100644 --- a/mysql-test/suite/galera/r/galera_sbr.result +++ b/mysql-test/suite/galera/r/galera_sbr.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; SET SESSION binlog_format = 'STATEMENT'; Warnings: diff --git a/mysql-test/suite/galera/r/galera_sbr_binlog.result b/mysql-test/suite/galera/r/galera_sbr_binlog.result index 0bdaeef5b8a..c5fdecece0e 100644 --- a/mysql-test/suite/galera/r/galera_sbr_binlog.result +++ b/mysql-test/suite/galera/r/galera_sbr_binlog.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; SET SESSION binlog_format = 'STATEMENT'; Warnings: diff --git a/mysql-test/suite/galera/r/galera_schema_dirty_reads.result b/mysql-test/suite/galera/r/galera_schema_dirty_reads.result index edf20da92c6..fbac9ff4eb7 100644 --- a/mysql-test/suite/galera/r/galera_schema_dirty_reads.result +++ b/mysql-test/suite/galera/r/galera_schema_dirty_reads.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; USE information_schema; SELECT * FROM SESSION_VARIABLES WHERE VARIABLE_NAME LIKE "wsrep_dirty_reads"; VARIABLE_NAME VARIABLE_VALUE diff --git a/mysql-test/suite/galera/r/galera_serializable.result b/mysql-test/suite/galera/r/galera_serializable.result index be3f93a081f..e3785663271 100644 --- a/mysql-test/suite/galera/r/galera_serializable.result +++ b/mysql-test/suite/galera/r/galera_serializable.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (id INT PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB; SET AUTOCOMMIT=OFF; @@ -9,7 +11,7 @@ connection node_2; INSERT INTO t1 VALUES (1,1); connection node_1; SELECT * FROM t1; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction ROLLBACK; DELETE FROM t1; connection node_1; @@ -22,7 +24,7 @@ connection node_2; UPDATE t1 SET f2 = 2; connection node_1; UPDATE t1 SET f2 = 3; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction ROLLBACK; DELETE FROM t1; connection node_1; @@ -33,5 +35,5 @@ connection node_2; INSERT INTO t1 VALUES (1,2); connection node_1; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_server.result b/mysql-test/suite/galera/r/galera_server.result index cc08b826e82..5130dee3459 100644 --- a/mysql-test/suite/galera/r/galera_server.result +++ b/mysql-test/suite/galera/r/galera_server.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; # On node_1 CREATE SERVER s1 diff --git a/mysql-test/suite/galera/r/galera_sql_log_bin_zero.result b/mysql-test/suite/galera/r/galera_sql_log_bin_zero.result index 14407c917a1..e9f81192386 100644 --- a/mysql-test/suite/galera/r/galera_sql_log_bin_zero.result +++ b/mysql-test/suite/galera/r/galera_sql_log_bin_zero.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; SET SESSION sql_log_bin = 0; INSERT INTO t1 VALUES (1); diff --git a/mysql-test/suite/galera/r/galera_ssl.result b/mysql-test/suite/galera/r/galera_ssl.result index 022d06319b8..ec3b717e3f3 100644 --- a/mysql-test/suite/galera/r/galera_ssl.result +++ b/mysql-test/suite/galera/r/galera_ssl.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; VARIABLE_VALUE = 'Synced' 1 diff --git a/mysql-test/suite/galera/r/galera_ssl_compression.result b/mysql-test/suite/galera/r/galera_ssl_compression.result index 333d646376c..0acc4b97eea 100644 --- a/mysql-test/suite/galera/r/galera_ssl_compression.result +++ b/mysql-test/suite/galera/r/galera_ssl_compression.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; VARIABLE_VALUE = 'Synced' 1 diff --git a/mysql-test/suite/galera/r/galera_sst_mysqldump.result b/mysql-test/suite/galera/r/galera_sst_mysqldump.result index 5c530c32ce6..ec0fedf6664 100644 --- a/mysql-test/suite/galera/r/galera_sst_mysqldump.result +++ b/mysql-test/suite/galera/r/galera_sst_mysqldump.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; Setting SST method to mysqldump ... call mtr.add_suppression("WSREP: wsrep_sst_method is set to 'mysqldump' yet mysqld bind_address is set to '127.0.0.1'"); call mtr.add_suppression("Failed to load slave replication state from table mysql.gtid_slave_pos"); @@ -56,6 +58,9 @@ INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); INSERT INTO t1 VALUES ('node1_to_be_rollbacked_after'); connection node_2; Loading wsrep provider ... +disconnect node_2; +connect node_2, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_2; SET AUTOCOMMIT=OFF; START TRANSACTION; INSERT INTO t1 VALUES ('node2_committed_after'); @@ -390,6 +395,114 @@ COUNT(*) = 0 DROP TABLE t1; COMMIT; SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +while a DDL was in progress on it +connection node_1; +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +connection node_2; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +SET GLOBAL debug_dbug = 'd,sync.alter_opened_table'; +connection node_1; +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +connection node_2; +SET wsrep_sync_wait = 0; +Killing server ... +connection node_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +connection node_2; +Performing --wsrep-recover ... +connection node_2; +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +COMMIT; +connection node_1; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +COMMIT; +connection node_1a_galera_st_kill_slave_ddl; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +connection node_1; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +SET GLOBAL debug_dbug = $debug_orig; connection node_1; CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query"); DROP USER sst; @@ -400,3 +513,4 @@ CALL mtr.add_suppression("Can't open and lock time zone table"); CALL mtr.add_suppression("Can't open and lock privilege tables"); CALL mtr.add_suppression("Info table is not ready to be used"); CALL mtr.add_suppression("Native table .* has the wrong structure"); +CALL mtr.add_suppression("Table \'mysql.gtid_slave_pos\' doesn\'t exist"); diff --git a/mysql-test/suite/galera/r/galera_sst_rsync.result b/mysql-test/suite/galera/r/galera_sst_rsync.result index ff85a7d6c0f..dbeab68fa17 100644 --- a/mysql-test/suite/galera/r/galera_sst_rsync.result +++ b/mysql-test/suite/galera/r/galera_sst_rsync.result @@ -1,5 +1,5 @@ -connection node_1; connection node_2; +connection node_1; Performing State Transfer on a server that has been shut down cleanly and restarted connection node_1; CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; diff --git a/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2.result b/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2.result index fdb5883b590..f371bf1a948 100644 --- a/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2.result +++ b/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; connection node_2; Performing State Transfer on a server that has been shut down cleanly and restarted @@ -286,5 +288,113 @@ COUNT(*) = 0 DROP TABLE t1; COMMIT; SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +while a DDL was in progress on it +connection node_1; +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +connection node_2; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +SET GLOBAL debug_dbug = 'd,sync.alter_opened_table'; +connection node_1; +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +connection node_2; +SET wsrep_sync_wait = 0; +Killing server ... +connection node_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); +COMMIT; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +connection node_2; +Performing --wsrep-recover ... +connection node_2; +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +COMMIT; +connection node_1; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +COMMIT; +connection node_1a_galera_st_kill_slave_ddl; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +ROLLBACK; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +COMMIT; +SET AUTOCOMMIT=ON; +connection node_1; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 35 FROM t1; +COUNT(*) = 35 +1 +SELECT COUNT(*) = 0 FROM (SELECT COUNT(*) AS c, f1 FROM t1 GROUP BY f1 HAVING c NOT IN (5, 10)) AS a1; +COUNT(*) = 0 +1 +DROP TABLE t1; +COMMIT; +SET AUTOCOMMIT=ON; +SET GLOBAL debug_dbug = $debug_orig; disconnect node_2; disconnect node_1; diff --git a/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2_encrypt_with_key.result b/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2_encrypt_with_key.result index 990e0a29506..409da775d9a 100644 --- a/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2_encrypt_with_key.result +++ b/mysql-test/suite/galera/r/galera_sst_xtrabackup-v2_encrypt_with_key.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; SELECT 1; 1 1 diff --git a/mysql-test/suite/galera/r/galera_status_cluster.result b/mysql-test/suite/galera/r/galera_status_cluster.result index ad92a51b775..9db0b88adc9 100644 --- a/mysql-test/suite/galera/r/galera_status_cluster.result +++ b/mysql-test/suite/galera/r/galera_status_cluster.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 2 diff --git a/mysql-test/suite/galera/r/galera_status_local_index.result b/mysql-test/suite/galera/r/galera_status_local_index.result index 8c36b60cc5f..c67498fff9f 100644 --- a/mysql-test/suite/galera/r/galera_status_local_index.result +++ b/mysql-test/suite/galera/r/galera_status_local_index.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE wsrep_local_indexes (wsrep_local_index INTEGER); INSERT INTO wsrep_local_indexes VALUES ((SELECT variable_value FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE variable_name = 'wsrep_local_index')); diff --git a/mysql-test/suite/galera/r/galera_status_local_state.result b/mysql-test/suite/galera/r/galera_status_local_state.result index 65713f1975c..3fe988ee6ac 100644 --- a/mysql-test/suite/galera/r/galera_status_local_state.result +++ b/mysql-test/suite/galera/r/galera_status_local_state.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state'; VARIABLE_VALUE = 4 1 diff --git a/mysql-test/suite/galera/r/galera_suspend_slave.result b/mysql-test/suite/galera/r/galera_suspend_slave.result index 3b950e82e33..2f35be2da93 100644 --- a/mysql-test/suite/galera/r/galera_suspend_slave.result +++ b/mysql-test/suite/galera/r/galera_suspend_slave.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; connection node_2; connection node_1; diff --git a/mysql-test/suite/galera/r/galera_sync_wait_show.result b/mysql-test/suite/galera/r/galera_sync_wait_show.result index def771ff88d..793da3246ff 100644 --- a/mysql-test/suite/galera/r/galera_sync_wait_show.result +++ b/mysql-test/suite/galera/r/galera_sync_wait_show.result @@ -1,4 +1,6 @@ connection node_2; +connection node_1; +connection node_2; SET SESSION wsrep_sync_wait = 8; connection node_1; CREATE DATABASE db1; diff --git a/mysql-test/suite/galera/r/galera_toi_alter_auto_increment.result b/mysql-test/suite/galera/r/galera_toi_alter_auto_increment.result index 8a86dfd11e2..a23b0523140 100644 --- a/mysql-test/suite/galera/r/galera_toi_alter_auto_increment.result +++ b/mysql-test/suite/galera/r/galera_toi_alter_auto_increment.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); diff --git a/mysql-test/suite/galera/r/galera_toi_ddl_error.result b/mysql-test/suite/galera/r/galera_toi_ddl_error.result index dafad153867..386dc28bed3 100644 --- a/mysql-test/suite/galera/r/galera_toi_ddl_error.result +++ b/mysql-test/suite/galera/r/galera_toi_ddl_error.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; @@ -19,3 +21,6 @@ t1 CREATE TABLE `t1` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1 DROP TABLE t1; DROP TABLE ten; +CALL mtr.add_suppression("Ignoring error 'Duplicate entry '111110' for key 'PRIMARY'' on query."); +connection node_2; +CALL mtr.add_suppression("Ignoring error 'Duplicate entry '111110' for key 'PRIMARY'' on query."); diff --git a/mysql-test/suite/galera/r/galera_toi_ddl_fk_update.result b/mysql-test/suite/galera/r/galera_toi_ddl_fk_update.result index a5db90aa965..a7966e36133 100644 --- a/mysql-test/suite/galera/r/galera_toi_ddl_fk_update.result +++ b/mysql-test/suite/galera/r/galera_toi_ddl_fk_update.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); CREATE TABLE parent ( diff --git a/mysql-test/suite/galera/r/galera_toi_ddl_locking.result b/mysql-test/suite/galera/r/galera_toi_ddl_locking.result index 68743c024a0..4dd996093ec 100644 --- a/mysql-test/suite/galera/r/galera_toi_ddl_locking.result +++ b/mysql-test/suite/galera/r/galera_toi_ddl_locking.result @@ -1,32 +1,46 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_sync_wait = 0; connection node_1; -SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue'; +SET DEBUG_SYNC= 'RESET'; +SET DEBUG_SYNC = 'alter_table_before_open_tables SIGNAL before_open_tables WAIT_FOR continue'; ALTER TABLE t1 ADD COLUMN f2 INTEGER;; connection node_1a; -SET SESSION wsrep_sync_wait = 0; +SET DEBUG_SYNC= 'now WAIT_FOR before_open_tables'; +SET wsrep_retry_autocommit=0; SELECT COUNT(*) = 0 FROM t1; COUNT(*) = 0 1 SELECT COUNT(*) = 0 FROM t2; COUNT(*) = 0 1 -INSERT INTO t1 VALUES (1); -Got one of the listed errors +INSERT INTO t1 VALUES (1);; +connection node_1c; +SET SESSION wsrep_sync_wait = 0; SET AUTOCOMMIT=OFF; START TRANSACTION; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t2; +COUNT(*) = 0 +1 INSERT INTO t2 VALUES (1); COMMIT;; connection node_1b; SET SESSION wsrep_sync_wait = 0; -SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'Commit'; -COUNT(*) = 1 -1 SELECT COUNT(*) = 0 FROM t2; COUNT(*) = 0 1 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'Commit'; +COUNT(*) = 1 +1 SET DEBUG_SYNC= 'now SIGNAL continue'; connection node_1a; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +connection node_1c; connection node_1; SELECT COUNT(*) = 0 FROM t1; COUNT(*) = 0 @@ -41,9 +55,5 @@ COUNT(*) = 0 SELECT COUNT(*) = 1 FROM t2; COUNT(*) = 1 1 -connection node_1; -SET DEBUG_SYNC= 'RESET'; -connection node_1b; -SET DEBUG_SYNC= 'RESET'; DROP TABLE t1; DROP TABLE t2; diff --git a/mysql-test/suite/galera/r/galera_toi_ddl_nonconflicting.result b/mysql-test/suite/galera/r/galera_toi_ddl_nonconflicting.result index 3844fa97d82..5412cd3faee 100644 --- a/mysql-test/suite/galera/r/galera_toi_ddl_nonconflicting.result +++ b/mysql-test/suite/galera/r/galera_toi_ddl_nonconflicting.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 INTEGER); connection node_2; ALTER TABLE t1 ADD COLUMN f3 INTEGER; INSERT INTO t1 (f1, f2) VALUES (DEFAULT, 123);; diff --git a/mysql-test/suite/galera/r/galera_toi_ddl_sequential.result b/mysql-test/suite/galera/r/galera_toi_ddl_sequential.result index 722bb9d9e12..db702b1a59e 100644 --- a/mysql-test/suite/galera/r/galera_toi_ddl_sequential.result +++ b/mysql-test/suite/galera/r/galera_toi_ddl_sequential.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; diff --git a/mysql-test/suite/galera/r/galera_toi_drop_database.result b/mysql-test/suite/galera/r/galera_toi_drop_database.result index 6d88c8ea230..48056c70126 100644 --- a/mysql-test/suite/galera/r/galera_toi_drop_database.result +++ b/mysql-test/suite/galera/r/galera_toi_drop_database.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE DATABASE database1; USE database1; @@ -14,9 +16,9 @@ INSERT INTO t2 (f1) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, te connection node_2; DROP DATABASE database1;; connection node_1; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction connection node_1a; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction connection node_2; connection node_1; SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'database1'; diff --git a/mysql-test/suite/galera/r/galera_toi_ftwrl.result b/mysql-test/suite/galera/r/galera_toi_ftwrl.result index 0f13e95b689..fdc8b294c1c 100644 --- a/mysql-test/suite/galera/r/galera_toi_ftwrl.result +++ b/mysql-test/suite/galera/r/galera_toi_ftwrl.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; connection node_2; FLUSH TABLES WITH READ LOCK; diff --git a/mysql-test/suite/galera/r/galera_toi_lock_exclusive.result b/mysql-test/suite/galera/r/galera_toi_lock_exclusive.result index f5cc14ed0f1..ee8c826fd18 100644 --- a/mysql-test/suite/galera/r/galera_toi_lock_exclusive.result +++ b/mysql-test/suite/galera/r/galera_toi_lock_exclusive.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; @@ -8,7 +10,7 @@ connection node_2a; ALTER TABLE t1 ADD COLUMN f2 INTEGER, LOCK=EXCLUSIVE; connection node_2; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction connection node_1; INSERT INTO t1 VALUES (2, 2); SELECT COUNT(*) = 2 FROM t1; diff --git a/mysql-test/suite/galera/r/galera_toi_lock_shared.result b/mysql-test/suite/galera/r/galera_toi_lock_shared.result index 950c4d83c70..fe1c88075d5 100644 --- a/mysql-test/suite/galera/r/galera_toi_lock_shared.result +++ b/mysql-test/suite/galera/r/galera_toi_lock_shared.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; diff --git a/mysql-test/suite/galera/r/galera_toi_truncate.result b/mysql-test/suite/galera/r/galera_toi_truncate.result index 933379cade5..14580e55bb7 100644 --- a/mysql-test/suite/galera/r/galera_toi_truncate.result +++ b/mysql-test/suite/galera/r/galera_toi_truncate.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); @@ -9,7 +11,7 @@ connection node_1; TRUNCATE TABLE t1;; connection node_1; connection node_2; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction connection node_2; SELECT COUNT(*) = 0 FROM t1; COUNT(*) = 0 diff --git a/mysql-test/suite/galera/r/galera_transaction_read_only.result b/mysql-test/suite/galera/r/galera_transaction_read_only.result index b388f195fb1..55923f58b65 100644 --- a/mysql-test/suite/galera/r/galera_transaction_read_only.result +++ b/mysql-test/suite/galera/r/galera_transaction_read_only.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; connection node_2; diff --git a/mysql-test/suite/galera/r/galera_transaction_replay.result b/mysql-test/suite/galera/r/galera_transaction_replay.result index 7fd837433d2..272086c4eba 100644 --- a/mysql-test/suite/galera/r/galera_transaction_replay.result +++ b/mysql-test/suite/galera/r/galera_transaction_replay.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)); INSERT INTO t1 VALUES (1, 'a'); INSERT INTO t1 VALUES (2, 'a'); @@ -9,19 +11,73 @@ SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE; f1 f2 2 a connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; -SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_enter_sync'; +SET SESSION wsrep_sync_wait=0; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +UPDATE t1 SET f2 = 'c' WHERE f1 = 2; +connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync'; connection node_1; -COMMIT;; +COMMIT; connection node_1a; -SET SESSION wsrep_sync_wait = 0; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync'; +connection node_1; +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; +COUNT(*) = 1 +1 +wsrep_local_replays +1 connection node_2; -UPDATE t1 SET f2 = 'c' WHERE f1 = 2; +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; +COUNT(*) = 1 +1 +DROP TABLE t1; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)); +INSERT INTO t1 VALUES (1, 'a'); +INSERT INTO t1 VALUES (2, 'a'); +connection node_1; +SET AUTOCOMMIT=ON; +START TRANSACTION; +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE; +f1 f2 +2 a +SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync'; +connection node_1; +COMMIT; connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +connection node_2; +UPDATE t1 SET f2 = 'c' WHERE f1 = 2; connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; SET GLOBAL wsrep_provider_options = 'dbug='; -SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync'; connection node_1; SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b'; COUNT(*) = 1 @@ -46,22 +102,34 @@ SELECT * FROM t1; i j 1 0 3 0 +SET AUTOCOMMIT=ON; PREPARE stmt1 FROM "UPDATE t1 SET j = 1 where i > 0"; connection node_1a; -SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_enter_sync'; -connection node_1; -EXECUTE stmt1;; -connection node_1a; -SET SESSION wsrep_sync_wait = 0; -SET SESSION wsrep_on = 0; -SET SESSION wsrep_on = 1; +SET SESSION wsrep_sync_wait=0; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; connection node_2; INSERT INTO t1 VALUES(2,2); connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync'; +connection node_1; +SET SESSION wsrep_sync_wait=0; +EXECUTE stmt1; connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'dbug='; -SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_enter_sync'; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync'; connection node_1; +SET SESSION wsrep_sync_wait=7; SELECT * FROM t1; i j 1 1 @@ -74,5 +142,7 @@ i j 2 2 3 1 connection node_1; +wsrep_local_replays +1 DEALLOCATE PREPARE stmt1; DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_truncate.result b/mysql-test/suite/galera/r/galera_truncate.result index 4f3d72dbca7..c649d9bbaf9 100644 --- a/mysql-test/suite/galera/r/galera_truncate.result +++ b/mysql-test/suite/galera/r/galera_truncate.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; diff --git a/mysql-test/suite/galera/r/galera_truncate_temporary.result b/mysql-test/suite/galera/r/galera_truncate_temporary.result index 183ebd9d24a..81373bda739 100644 --- a/mysql-test/suite/galera/r/galera_truncate_temporary.result +++ b/mysql-test/suite/galera/r/galera_truncate_temporary.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TEMPORARY TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; INSERT INTO t1 VALUES (1); TRUNCATE TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_unicode_identifiers.result b/mysql-test/suite/galera/r/galera_unicode_identifiers.result index 5eb13a83df9..495c508d59f 100644 --- a/mysql-test/suite/galera/r/galera_unicode_identifiers.result +++ b/mysql-test/suite/galera/r/galera_unicode_identifiers.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; SET GLOBAL wsrep_sync_wait = 15; connection node_2; SET GLOBAL wsrep_sync_wait = 15; diff --git a/mysql-test/suite/galera/r/galera_unicode_pk.result b/mysql-test/suite/galera/r/galera_unicode_pk.result index 0e8965a76e3..bb36fd4f369 100644 --- a/mysql-test/suite/galera/r/galera_unicode_pk.result +++ b/mysql-test/suite/galera/r/galera_unicode_pk.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 ( f1 VARCHAR(255) PRIMARY KEY ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -18,7 +20,7 @@ connection node_1; COMMIT; connection node_2; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction SELECT f1 = 'текст2' FROM t1; f1 = 'текст2' 1 @@ -35,6 +37,6 @@ connection node_2; COMMIT; connection node_1; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction COMMIT; DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_update_limit.result b/mysql-test/suite/galera/r/galera_update_limit.result index 20a94e6f504..30c89a38dff 100644 --- a/mysql-test/suite/galera/r/galera_update_limit.result +++ b/mysql-test/suite/galera/r/galera_update_limit.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE ten (f1 INTEGER) Engine=InnoDB; INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); diff --git a/mysql-test/suite/galera/r/galera_v1_row_events.result b/mysql-test/suite/galera/r/galera_v1_row_events.result index b0ea2293119..80fe2fb6d8d 100644 --- a/mysql-test/suite/galera/r/galera_v1_row_events.result +++ b/mysql-test/suite/galera/r/galera_v1_row_events.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; diff --git a/mysql-test/suite/galera/r/galera_var_OSU_method.result b/mysql-test/suite/galera/r/galera_var_OSU_method.result index 18e8bd2271a..2b0a713e86b 100644 --- a/mysql-test/suite/galera/r/galera_var_OSU_method.result +++ b/mysql-test/suite/galera/r/galera_var_OSU_method.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; connection node_1; SET SESSION wsrep_OSU_method = "RSU"; diff --git a/mysql-test/suite/galera/r/galera_var_OSU_method2.result b/mysql-test/suite/galera/r/galera_var_OSU_method2.result index 0e3751645a8..ca4f617d903 100644 --- a/mysql-test/suite/galera/r/galera_var_OSU_method2.result +++ b/mysql-test/suite/galera/r/galera_var_OSU_method2.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; connection node_1; SET SESSION wsrep_OSU_method = "TOI"; diff --git a/mysql-test/suite/galera/r/galera_var_auto_inc_control_off.result b/mysql-test/suite/galera/r/galera_var_auto_inc_control_off.result index ba117b4c2d5..86c30fa4b23 100644 --- a/mysql-test/suite/galera/r/galera_var_auto_inc_control_off.result +++ b/mysql-test/suite/galera/r/galera_var_auto_inc_control_off.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; SET GLOBAL wsrep_auto_increment_control = OFF; SET GLOBAL auto_increment_increment = 1; @@ -59,7 +61,7 @@ connection node_1a; COMMIT; connection node_2a; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction connection node_1a; SELECT * FROM t1; f1 node diff --git a/mysql-test/suite/galera/r/galera_var_certify_nonPK_off.result b/mysql-test/suite/galera/r/galera_var_certify_nonPK_off.result index ca3844bf6bf..f5472aa931f 100644 --- a/mysql-test/suite/galera/r/galera_var_certify_nonPK_off.result +++ b/mysql-test/suite/galera/r/galera_var_certify_nonPK_off.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; SET GLOBAL wsrep_certify_nonPK = OFF; connection node_2; SET GLOBAL wsrep_certify_nonPK = OFF; diff --git a/mysql-test/suite/galera/r/galera_var_cluster_address.result b/mysql-test/suite/galera/r/galera_var_cluster_address.result index 378d8ca84f5..cf1e60c8425 100644 --- a/mysql-test/suite/galera/r/galera_var_cluster_address.result +++ b/mysql-test/suite/galera/r/galera_var_cluster_address.result @@ -1,7 +1,11 @@ +connection node_2; +connection node_1; connection node_1; connection node_2; connection node_2; SET GLOBAL wsrep_cluster_address = 'foo://'; +SHOW STATUS; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET SESSION wsrep_sync_wait=0; SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS; COUNT(*) > 0 @@ -39,7 +43,7 @@ CALL mtr.add_suppression("Failed to initialize backend using 'foo"); CALL mtr.add_suppression("Failed to open channel 'my_wsrep_cluster' at 'foo"); CALL mtr.add_suppression("gcs connect failed: Socket type not supported"); CALL mtr.add_suppression("wsrep::connect\\(\\) failed: 7"); -CALL mtr.add_suppression("gcs_caused\\(\\) returned -103 \\(Software caused connection abort\\)"); +CALL mtr.add_suppression("gcs_caused\\(\\) returned -[0-9]+ \\(Software caused connection abort\\)"); CALL mtr.add_suppression("failed to open gcomm backend connection: 110: failed to reach primary view: 110"); CALL mtr.add_suppression("Failed to open backend connection: -110 \\(Connection timed out\\)"); CALL mtr.add_suppression("gcs connect failed: Connection timed out"); diff --git a/mysql-test/suite/galera/r/galera_var_desync_on.result b/mysql-test/suite/galera/r/galera_var_desync_on.result index a26acbd4d6b..06304a6ed35 100644 --- a/mysql-test/suite/galera/r/galera_var_desync_on.result +++ b/mysql-test/suite/galera/r/galera_var_desync_on.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; diff --git a/mysql-test/suite/galera/r/galera_var_dirty_reads.result b/mysql-test/suite/galera/r/galera_var_dirty_reads.result index 049aa5be3cc..ca10ba38939 100644 --- a/mysql-test/suite/galera/r/galera_var_dirty_reads.result +++ b/mysql-test/suite/galera/r/galera_var_dirty_reads.result @@ -1,4 +1,3 @@ -connection node_1; connection node_2; connection node_1; connection node_2; diff --git a/mysql-test/suite/galera/r/galera_var_fkchecks.result b/mysql-test/suite/galera/r/galera_var_fkchecks.result index 8b1b913a584..42f8085ee1a 100644 --- a/mysql-test/suite/galera/r/galera_var_fkchecks.result +++ b/mysql-test/suite/galera/r/galera_var_fkchecks.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE parent ( id INT PRIMARY KEY, KEY (id) diff --git a/mysql-test/suite/galera/r/galera_var_gtid_domain_id.result b/mysql-test/suite/galera/r/galera_var_gtid_domain_id.result index 1a8733e2e1a..d2faf5ff463 100644 --- a/mysql-test/suite/galera/r/galera_var_gtid_domain_id.result +++ b/mysql-test/suite/galera/r/galera_var_gtid_domain_id.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; # On node_1 connection node_1; list of GTID variables : diff --git a/mysql-test/suite/galera/r/galera_var_ignore_apply_errors.result b/mysql-test/suite/galera/r/galera_var_ignore_apply_errors.result new file mode 100644 index 00000000000..39bab15ef13 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_var_ignore_apply_errors.result @@ -0,0 +1,154 @@ +SET GLOBAL wsrep_ignore_apply_errors = 1; +SET GLOBAL wsrep_on = OFF; +CREATE TABLE t1 (f1 INTEGER); +SET GLOBAL wsrep_on = ON; +DROP TABLE t1; +SET GLOBAL wsrep_on = OFF; +CREATE SCHEMA s1; +SET GLOBAL wsrep_on = ON; +DROP SCHEMA s1; +CREATE TABLE t1 (f1 INTEGER); +SET GLOBAL wsrep_on = OFF; +CREATE INDEX idx1 ON t1 (f1); +SET GLOBAL wsrep_on = ON; +DROP INDEX idx1 ON t1; +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER); +SET GLOBAL wsrep_on = OFF; +CREATE INDEX idx1 ON t1 (f1); +SET GLOBAL wsrep_on = ON; +ALTER TABLE t1 DROP INDEX idx1; +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER); +SET GLOBAL wsrep_on = OFF; +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +SET GLOBAL wsrep_on = ON; +ALTER TABLE t1 DROP COLUMN f2; +DROP TABLE t1; +SET GLOBAL wsrep_ignore_apply_errors = 2; +CREATE TABLE t1 (f1 INTEGER); +SET GLOBAL wsrep_on = OFF; +INSERT INTO t1 VALUES (1); +SET GLOBAL wsrep_on = ON; +DELETE FROM t1 WHERE f1 = 1; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER); +INSERT INTO t1 VALUES (2); +SET GLOBAL wsrep_on = OFF; +INSERT INTO t1 VALUES (1); +SET GLOBAL wsrep_on = ON; +START TRANSACTION; +INSERT INTO t1 VALUES (3); +DELETE FROM t1 WHERE f1 = 1; +DELETE FROM t1 WHERE f1 = 2; +COMMIT; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +SET SESSION wsrep_on = OFF; +DELETE FROM t1 WHERE f1 = 3; +SET SESSION wsrep_on = ON; +DELETE FROM t1; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +SET SESSION wsrep_on = OFF; +DELETE FROM t1 WHERE f1 = 3; +SET SESSION wsrep_on = ON; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +DELETE FROM t1 WHERE f1 = 1; +DELETE FROM t1 WHERE f1 = 2; +DELETE FROM t1 WHERE f1 = 3; +DELETE FROM t1 WHERE f1 = 4; +DELETE FROM t1 WHERE f1 = 5; +COMMIT; +SET AUTOCOMMIT=ON; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3); +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3); +SET SESSION wsrep_on = OFF; +DELETE FROM t2 WHERE f1 = 2; +DELETE FROM t1 WHERE f1 = 3; +SET SESSION wsrep_on = ON; +DELETE t1, t2 FROM t1 JOIN t2 WHERE t1.f1 = t2.f1; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +DROP TABLE t1,t2; +CREATE TABLE parent (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB; +INSERT INTO parent VALUES (1),(2),(3); +CREATE TABLE child (id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE) ENGINE=INNODB; +INSERT INTO child VALUES (1,1),(2,2),(3,3); +SET SESSION wsrep_on = OFF; +DELETE FROM child WHERE parent_id = 2; +SET SESSION wsrep_on = ON; +DELETE FROM parent; +SELECT COUNT(*) = 0 FROM parent; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM child; +COUNT(*) = 0 +1 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT COUNT(*) = 0 FROM parent; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM child; +COUNT(*) = 0 +1 +DROP TABLE child, parent; +SET GLOBAL wsrep_ignore_apply_errors = 4; +SET GLOBAL wsrep_on = OFF; +CREATE TABLE t1 (f1 INTEGER); +SET GLOBAL wsrep_on = ON; +CREATE TABLE t1 (f1 INTEGER, f2 INTEGER); +DROP TABLE t1; +SET GLOBAL wsrep_ignore_apply_errors = 7; +CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows event"); +CALL mtr.add_suppression("Slave SQL: Error 'Unknown table 'test.t1'' on query. Default database: 'test'. Query: 'DROP TABLE t1', Error_code: 1051"); +CALL mtr.add_suppression("Slave SQL: Error 'Can't drop database 's1'; database doesn't exist' on query. Default database: 'test'. Query: 'DROP SCHEMA s1', Error_code: 1008"); +CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'idx1'; check that column/key exists' on query. Default database: 'test'. Query: 'DROP INDEX idx1 ON t1', Error_code: 1091"); +CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'idx1'; check that column/key exists' on query. Default database: 'test'. Query: 'ALTER TABLE t1 DROP INDEX idx1', Error_code: 1091"); +CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'f2'; check that column/key exists' on query. Default database: 'test'. Query: 'ALTER TABLE t1 DROP COLUMN f2', Error_code: 1091"); +CALL mtr.add_suppression("Slave SQL: Error 'Table 't1' already exists' on query."); diff --git a/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result b/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result index 4db4e539c50..f5ec473fea4 100644 --- a/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result +++ b/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1a; SET SESSION wsrep_sync_wait = 0; connection node_1; diff --git a/mysql-test/suite/galera/r/galera_var_load_data_splitting.result b/mysql-test/suite/galera/r/galera_var_load_data_splitting.result index 3e451abbed1..7c5fd44356e 100644 --- a/mysql-test/suite/galera/r/galera_var_load_data_splitting.result +++ b/mysql-test/suite/galera/r/galera_var_load_data_splitting.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; connection node_2; SET GLOBAL wsrep_load_data_splitting = TRUE; diff --git a/mysql-test/suite/galera/r/galera_var_log_bin.result b/mysql-test/suite/galera/r/galera_var_log_bin.result index b0ea2293119..80fe2fb6d8d 100644 --- a/mysql-test/suite/galera/r/galera_var_log_bin.result +++ b/mysql-test/suite/galera/r/galera_var_log_bin.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; diff --git a/mysql-test/suite/galera/r/galera_var_max_ws_rows.result b/mysql-test/suite/galera/r/galera_var_max_ws_rows.result index 6bf67a3fb60..16e868f0485 100644 --- a/mysql-test/suite/galera/r/galera_var_max_ws_rows.result +++ b/mysql-test/suite/galera/r/galera_var_max_ws_rows.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB; diff --git a/mysql-test/suite/galera/r/galera_var_max_ws_size.result b/mysql-test/suite/galera/r/galera_var_max_ws_size.result index 53bac04fa86..89c9698eed4 100644 --- a/mysql-test/suite/galera/r/galera_var_max_ws_size.result +++ b/mysql-test/suite/galera/r/galera_var_max_ws_size.result @@ -1,8 +1,10 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(1024)) Engine=InnoDB; SET GLOBAL wsrep_max_ws_size = 1024; INSERT INTO t1 VALUES (DEFAULT, REPEAT('X', 1024)); -ERROR HY000: Got error 90 "Message too long" during COMMIT +ERROR HY000: Got error 5 "Input/output error" during COMMIT SELECT COUNT(*) = 0 FROM t1; COUNT(*) = 0 1 diff --git a/mysql-test/suite/galera/r/galera_var_mysql_replication_bundle.result b/mysql-test/suite/galera/r/galera_var_mysql_replication_bundle.result index 202633a020e..d7a38d24722 100644 --- a/mysql-test/suite/galera/r/galera_var_mysql_replication_bundle.result +++ b/mysql-test/suite/galera/r/galera_var_mysql_replication_bundle.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INT PRIMARY KEY) Engine=InnoDB; SET GLOBAL wsrep_mysql_replication_bundle = 2; connection node_1; diff --git a/mysql-test/suite/galera/r/galera_var_node_address.result b/mysql-test/suite/galera/r/galera_var_node_address.result index b8076958532..2538c913a96 100644 --- a/mysql-test/suite/galera/r/galera_var_node_address.result +++ b/mysql-test/suite/galera/r/galera_var_node_address.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; call mtr.add_suppression("WSREP: Stray state UUID msg: .* current group state WAIT_STATE_UUID .*"); call mtr.add_suppression("WSREP: Protocol violation. JOIN message sender .* is not in state transfer (.*). Message ignored."); call mtr.add_suppression("WSREP: Sending JOIN failed: -[0-9]+ (Transport endpoint is not connected). Will retry in new primary component."); diff --git a/mysql-test/suite/galera/r/galera_var_reject_queries.result b/mysql-test/suite/galera/r/galera_var_reject_queries.result index 98380238fcb..e986092ea59 100644 --- a/mysql-test/suite/galera/r/galera_var_reject_queries.result +++ b/mysql-test/suite/galera/r/galera_var_reject_queries.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER); connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; connection node_1; diff --git a/mysql-test/suite/galera/r/galera_var_replicate_myisam_off.result b/mysql-test/suite/galera/r/galera_var_replicate_myisam_off.result index 382466b1387..8968f89d11b 100644 --- a/mysql-test/suite/galera/r/galera_var_replicate_myisam_off.result +++ b/mysql-test/suite/galera/r/galera_var_replicate_myisam_off.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; SET GLOBAL wsrep_replicate_myisam = FALSE; CREATE TABLE t1 (f1 INT PRIMARY KEY) Engine=MyISAM; INSERT INTO t1 VALUES (1); diff --git a/mysql-test/suite/galera/r/galera_var_replicate_myisam_on.result b/mysql-test/suite/galera/r/galera_var_replicate_myisam_on.result index 87f8862df7e..716af033e7a 100644 --- a/mysql-test/suite/galera/r/galera_var_replicate_myisam_on.result +++ b/mysql-test/suite/galera/r/galera_var_replicate_myisam_on.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; connection node_1; SET GLOBAL wsrep_replicate_myisam = TRUE; diff --git a/mysql-test/suite/galera/r/galera_var_slave_threads.result b/mysql-test/suite/galera/r/galera_var_slave_threads.result index 3f0a63ab9d7..6196e6b1b78 100644 --- a/mysql-test/suite/galera/r/galera_var_slave_threads.result +++ b/mysql-test/suite/galera/r/galera_var_slave_threads.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (f1 INT PRIMARY KEY) Engine=InnoDB; CREATE TABLE t2 (f1 INT AUTO_INCREMENT PRIMARY KEY) Engine=InnoDB; @@ -13,13 +15,25 @@ SELECT @@wsrep_slave_threads = 1; @@wsrep_slave_threads = 1 1 SET GLOBAL wsrep_slave_threads = 1; -SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; -COUNT(*) +SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon'; +COUNT(*) = 3 +1 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; +COUNT(*) = 1 1 SET GLOBAL wsrep_slave_threads = 64; connection node_1; INSERT INTO t1 VALUES (1); connection node_2; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon'; +COUNT(*) = @@wsrep_slave_threads + 2 +0 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; +COUNT(*) = 1 +1 SET GLOBAL wsrep_slave_threads = 1; connection node_1; INSERT INTO t2 VALUES (DEFAULT); @@ -87,32 +101,188 @@ INSERT INTO t2 VALUES (DEFAULT); INSERT INTO t2 VALUES (DEFAULT); INSERT INTO t2 VALUES (DEFAULT); connection node_2; -SELECT COUNT(*) FROM t2; -COUNT(*) -64 +SELECT COUNT(*) = 64 FROM t2; +COUNT(*) = 64 +1 +SET wsrep_sync_wait=0; +SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon'; +COUNT(*) = @@wsrep_slave_threads + 2 +1 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; +COUNT(*) = 1 +1 SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; COUNT(*) 1 +SET GLOBAL wsrep_slave_threads = 5; SET GLOBAL wsrep_slave_threads = 1; -DROP TABLE t1; -DROP TABLE t2; -# -# lp:1372840 - Changing wsrep_slave_threads causes future connections to hang -# +connection node_2; +Shutting down server ... +connection node_1; +SET wsrep_sync_wait=0; +show status like 'wsrep_cluster_size'; +Variable_name Value +wsrep_cluster_size 1 +SET GLOBAL wsrep_slave_threads = 6; +SET GLOBAL wsrep_slave_threads = 1; +SET GLOBAL wsrep_cluster_address=''; +SET GLOBAL wsrep_cluster_address='gcomm://'; +SET GLOBAL wsrep_slave_threads = 10; +connection node_2; +SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon'; +COUNT(*) = @@wsrep_slave_threads + 2 +1 +connection node_1; +SET GLOBAL wsrep_slave_threads = 1; +connection node_2; +SET GLOBAL wsrep_slave_threads = 1; +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); connection node_1; -CREATE TABLE t1 (i INT AUTO_INCREMENT PRIMARY KEY) ENGINE=INNODB; +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); +INSERT INTO t2 VALUES (DEFAULT); connection node_2; SET GLOBAL wsrep_slave_threads = 4; +Timeout in wait_condition.inc for SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%') +Id User Host db Command Time State Info Progress +2 system user NULL Sleep 42 Waiting on cond NULL 0.000 +1 system user NULL Sleep 42 wsrep aborter idle NULL 0.000 +3 system user NULL Sleep 30 Committed 195 NULL 0.000 +4 system user NULL Daemon NULL InnoDB purge coordinator NULL 0.000 +5 system user NULL Daemon NULL InnoDB purge worker NULL 0.000 +7 system user NULL Daemon NULL InnoDB purge worker NULL 0.000 +6 system user NULL Daemon NULL InnoDB purge worker NULL 0.000 +8 system user NULL Daemon NULL InnoDB shutdown handler NULL 0.000 +27 root localhost:53510 test Query 0 Init show full processlist 0.000 +28 system user NULL Sleep 30 NULL NULL 0.000 +30 system user NULL Sleep 30 NULL NULL 0.000 +29 system user NULL Sleep 30 NULL NULL 0.000 SET GLOBAL wsrep_slave_threads = 1; connection node_1; -INSERT INTO t1 VALUES (DEFAULT); -INSERT INTO t1 VALUES (DEFAULT); -INSERT INTO t1 VALUES (DEFAULT); DROP TABLE t1; -connection node_2; -SELECT NAME FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t%'; -NAME -SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; -COUNT(*) = 1 -1 +DROP TABLE t2; # End of tests diff --git a/mysql-test/suite/galera/r/galera_var_sst_auth.result b/mysql-test/suite/galera/r/galera_var_sst_auth.result index 1db83197870..6a5683e2633 100644 --- a/mysql-test/suite/galera/r/galera_var_sst_auth.result +++ b/mysql-test/suite/galera/r/galera_var_sst_auth.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; # # MDEV-10492: Assertion failure on shutdown when wsrep_sst_auth set in config # diff --git a/mysql-test/suite/galera/r/galera_var_sync_wait.result b/mysql-test/suite/galera/r/galera_var_sync_wait.result index 3dfe902767c..80fbd3f3e05 100644 --- a/mysql-test/suite/galera/r/galera_var_sync_wait.result +++ b/mysql-test/suite/galera/r/galera_var_sync_wait.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; # # MDEV-10161: wsrep_sync_wait not enabled when set to 1 in config file # diff --git a/mysql-test/suite/galera/r/galera_var_wsrep_on_off.result b/mysql-test/suite/galera/r/galera_var_wsrep_on_off.result index 36340f505ff..5323bc9bf60 100644 --- a/mysql-test/suite/galera/r/galera_var_wsrep_on_off.result +++ b/mysql-test/suite/galera/r/galera_var_wsrep_on_off.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); SET SESSION wsrep_on = FALSE; diff --git a/mysql-test/suite/galera/r/galera_wan.result b/mysql-test/suite/galera/r/galera_wan.result index 73100636a0d..ff961c6e633 100644 --- a/mysql-test/suite/galera/r/galera_wan.result +++ b/mysql-test/suite/galera/r/galera_wan.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 4 1 diff --git a/mysql-test/suite/galera/r/galera_wan_restart_ist.result b/mysql-test/suite/galera/r/galera_wan_restart_ist.result index 8a2a7d0818e..7b87d534d92 100644 --- a/mysql-test/suite/galera/r/galera_wan_restart_ist.result +++ b/mysql-test/suite/galera/r/galera_wan_restart_ist.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4; connection node_1; diff --git a/mysql-test/suite/galera/r/galera_wan_restart_sst.result b/mysql-test/suite/galera/r/galera_wan_restart_sst.result index 71786cdd023..1296744a9c1 100644 --- a/mysql-test/suite/galera/r/galera_wan_restart_sst.result +++ b/mysql-test/suite/galera/r/galera_wan_restart_sst.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 4 1 diff --git a/mysql-test/suite/galera/r/galera_wsrep_desync_wsrep_on.result b/mysql-test/suite/galera/r/galera_wsrep_desync_wsrep_on.result index 99c680c7b12..e01825fd944 100644 --- a/mysql-test/suite/galera/r/galera_wsrep_desync_wsrep_on.result +++ b/mysql-test/suite/galera/r/galera_wsrep_desync_wsrep_on.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE ten (f1 INTEGER); INSERT INTO ten VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); diff --git a/mysql-test/suite/galera/r/galera_wsrep_log_conficts.result b/mysql-test/suite/galera/r/galera_wsrep_log_conficts.result index fa49d8c57c2..59883f1ca7e 100644 --- a/mysql-test/suite/galera/r/galera_wsrep_log_conficts.result +++ b/mysql-test/suite/galera/r/galera_wsrep_log_conficts.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 ( f1 VARCHAR(255) PRIMARY KEY ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -20,6 +22,6 @@ connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; connection node_2a; connection node_2; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction include/assert_grep.inc [cluster conflict due to high priority abort for threads] DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_wsrep_new_cluster.result b/mysql-test/suite/galera/r/galera_wsrep_new_cluster.result index ca388496794..8edf1a02e9d 100644 --- a/mysql-test/suite/galera/r/galera_wsrep_new_cluster.result +++ b/mysql-test/suite/galera/r/galera_wsrep_new_cluster.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; VARIABLE_VALUE = 'Primary' 1 diff --git a/mysql-test/suite/galera/r/galera_wsrep_provider_options_syntax.result b/mysql-test/suite/galera/r/galera_wsrep_provider_options_syntax.result index f19dc40205b..0f7cd134156 100644 --- a/mysql-test/suite/galera/r/galera_wsrep_provider_options_syntax.result +++ b/mysql-test/suite/galera/r/galera_wsrep_provider_options_syntax.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; call mtr.add_suppression("WSREP\: Unknown parameter 'gmcasts\.segment'"); call mtr.add_suppression("WSREP\: Set options returned 7"); SET GLOBAL wsrep_provider_options="gmcasts.segment=1"; diff --git a/mysql-test/suite/galera/r/galera_zero_length_column.result b/mysql-test/suite/galera/r/galera_zero_length_column.result index 572d94d6756..fa29264704f 100644 --- a/mysql-test/suite/galera/r/galera_zero_length_column.result +++ b/mysql-test/suite/galera/r/galera_zero_length_column.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY , f2 VARCHAR(0)) ENGINE=InnoDB; CREATE TABLE t2 (f1 VARCHAR(0)) ENGINE=InnoDB; diff --git a/mysql-test/suite/galera/r/grant.result b/mysql-test/suite/galera/r/grant.result index a2ca72ee8ec..0b5a34dfce1 100644 --- a/mysql-test/suite/galera/r/grant.result +++ b/mysql-test/suite/galera/r/grant.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; # # MDEV#6266: Changing password fails on galera cluster # diff --git a/mysql-test/suite/galera/r/lp1276424.result b/mysql-test/suite/galera/r/lp1276424.result index 363758e0d66..be27ee5374f 100644 --- a/mysql-test/suite/galera/r/lp1276424.result +++ b/mysql-test/suite/galera/r/lp1276424.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INT DEFAULT NULL, UNIQUE KEY i1 (f1)) ENGINE=InnoDB; INSERT INTO t1 VALUES (NULL); INSERT INTO t1 VALUES (NULL); diff --git a/mysql-test/suite/galera/r/lp1347768.result b/mysql-test/suite/galera/r/lp1347768.result index 7beb167d538..49c8894c081 100644 --- a/mysql-test/suite/galera/r/lp1347768.result +++ b/mysql-test/suite/galera/r/lp1347768.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE `r8kmb_redirect_links` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `old_url` varchar(255) DEFAULT NULL, diff --git a/mysql-test/suite/galera/r/lp1376747-2.result b/mysql-test/suite/galera/r/lp1376747-2.result index b85e130f4f4..5e5b5be6c86 100644 --- a/mysql-test/suite/galera/r/lp1376747-2.result +++ b/mysql-test/suite/galera/r/lp1376747-2.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; diff --git a/mysql-test/suite/galera/r/lp1376747-3.result b/mysql-test/suite/galera/r/lp1376747-3.result index a2c55b5f1f6..62893b85bcf 100644 --- a/mysql-test/suite/galera/r/lp1376747-3.result +++ b/mysql-test/suite/galera/r/lp1376747-3.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; diff --git a/mysql-test/suite/galera/r/lp1376747-4.result b/mysql-test/suite/galera/r/lp1376747-4.result index f1d32aa8f69..d6884cc3746 100644 --- a/mysql-test/suite/galera/r/lp1376747-4.result +++ b/mysql-test/suite/galera/r/lp1376747-4.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); diff --git a/mysql-test/suite/galera/r/lp1376747.result b/mysql-test/suite/galera/r/lp1376747.result index 16d4fa3fc52..1b9dd545409 100644 --- a/mysql-test/suite/galera/r/lp1376747.result +++ b/mysql-test/suite/galera/r/lp1376747.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; diff --git a/mysql-test/suite/galera/r/lp1438990.result b/mysql-test/suite/galera/r/lp1438990.result index d48d2435faa..a324121d7da 100644 --- a/mysql-test/suite/galera/r/lp1438990.result +++ b/mysql-test/suite/galera/r/lp1438990.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY); CREATE TABLE t2 (f1 INTEGER PRIMARY KEY); diff --git a/mysql-test/suite/galera/r/lp959512.result b/mysql-test/suite/galera/r/lp959512.result index 55adfa360b0..589030002db 100644 --- a/mysql-test/suite/galera/r/lp959512.result +++ b/mysql-test/suite/galera/r/lp959512.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; DROP TABLE IF EXISTS variable; Warnings: Note 1051 Unknown table 'test.variable' diff --git a/mysql-test/suite/galera/r/mdev_10518.result b/mysql-test/suite/galera/r/mdev_10518.result index 4ccd5fd1d23..252aa244f77 100644 --- a/mysql-test/suite/galera/r/mdev_10518.result +++ b/mysql-test/suite/galera/r/mdev_10518.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; # On node_1 connection node_1; list of GTID variables : diff --git a/mysql-test/suite/galera/r/mdev_9290.result b/mysql-test/suite/galera/r/mdev_9290.result index 276ab9e8ecb..d8fc35b02f4 100644 --- a/mysql-test/suite/galera/r/mdev_9290.result +++ b/mysql-test/suite/galera/r/mdev_9290.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; # # MDEV-9290 : InnoDB: Assertion failure in file trx0sys.cc line 353 # InnoDB: Failing assertion: xid_seqno > trx_sys_cur_xid_seqno diff --git a/mysql-test/suite/galera/r/mysql-wsrep#110.result b/mysql-test/suite/galera/r/mysql-wsrep#110.result index 6d4031d71cd..344185f4f4e 100644 --- a/mysql-test/suite/galera/r/mysql-wsrep#110.result +++ b/mysql-test/suite/galera/r/mysql-wsrep#110.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY); CREATE TABLE t2 (f1 INTEGER PRIMARY KEY); diff --git a/mysql-test/suite/galera/r/mysql-wsrep#198.result b/mysql-test/suite/galera/r/mysql-wsrep#198.result index 33f36d407db..5b569ffae27 100644 --- a/mysql-test/suite/galera/r/mysql-wsrep#198.result +++ b/mysql-test/suite/galera/r/mysql-wsrep#198.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB; connection node_2; diff --git a/mysql-test/suite/galera/r/mysql-wsrep#201.result b/mysql-test/suite/galera/r/mysql-wsrep#201.result index fe5725cab27..e55c38ea7cc 100644 --- a/mysql-test/suite/galera/r/mysql-wsrep#201.result +++ b/mysql-test/suite/galera/r/mysql-wsrep#201.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; INSERT INTO t1 VALUES (DEFAULT); connection node_2; diff --git a/mysql-test/suite/galera/r/mysql-wsrep#237.result b/mysql-test/suite/galera/r/mysql-wsrep#237.result index 19503dd5781..cf6f21f2112 100644 --- a/mysql-test/suite/galera/r/mysql-wsrep#237.result +++ b/mysql-test/suite/galera/r/mysql-wsrep#237.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t (f1 INTEGER PRIMARY KEY) Engine=InnoDB; connection node_1; SET DEBUG_SYNC = 'wsrep_before_replication WAIT_FOR continue'; diff --git a/mysql-test/suite/galera/r/mysql-wsrep#247.result b/mysql-test/suite/galera/r/mysql-wsrep#247.result index e59c6d1a299..704f0ba923c 100644 --- a/mysql-test/suite/galera/r/mysql-wsrep#247.result +++ b/mysql-test/suite/galera/r/mysql-wsrep#247.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; SET GLOBAL wsrep_desync=1; SET wsrep_OSU_method=RSU; diff --git a/mysql-test/suite/galera/r/mysql-wsrep#31.result b/mysql-test/suite/galera/r/mysql-wsrep#31.result index 1092f4ddb0c..d1d2861ec3a 100644 --- a/mysql-test/suite/galera/r/mysql-wsrep#31.result +++ b/mysql-test/suite/galera/r/mysql-wsrep#31.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; connection node_2; connection node_1; diff --git a/mysql-test/suite/galera/r/mysql-wsrep#90.result b/mysql-test/suite/galera/r/mysql-wsrep#90.result index 0b8f55e6219..b0fa06ffaf8 100644 --- a/mysql-test/suite/galera/r/mysql-wsrep#90.result +++ b/mysql-test/suite/galera/r/mysql-wsrep#90.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) Engine=InnoDB; connection node_1; SET GLOBAL wsrep_OSU_method = "RSU"; diff --git a/mysql-test/suite/galera/r/partition.result b/mysql-test/suite/galera/r/partition.result index 3835de514aa..774d5ce8f83 100644 --- a/mysql-test/suite/galera/r/partition.result +++ b/mysql-test/suite/galera/r/partition.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; # # MDEV#4953 Galera: DELETE from a partitioned table is not replicated # @@ -123,7 +125,7 @@ SELECT COUNT(*) = 20002 FROM t1; COUNT(*) = 20002 1 wsrep_last_committed_diff -1 +AS_EXPECTED_3_or_5 DROP TABLE t1; # Case 2: wsrep_load_data_splitting = ON & LOAD DATA with 101 entries. connection node_1; @@ -148,7 +150,7 @@ SELECT COUNT(*) = 20002 FROM t1; COUNT(*) = 20002 1 wsrep_last_committed_diff -1 +AS_EXPECTED_1_or_2 DROP TABLE t1; connection node_1; SET GLOBAL wsrep_load_data_splitting = 1;; diff --git a/mysql-test/suite/galera/r/pxc-421.result b/mysql-test/suite/galera/r/pxc-421.result index a317b3e40e1..058af15c098 100644 --- a/mysql-test/suite/galera/r/pxc-421.result +++ b/mysql-test/suite/galera/r/pxc-421.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; connection node_2; connection node_1; diff --git a/mysql-test/suite/galera/r/query_cache.result b/mysql-test/suite/galera/r/query_cache.result index d497fc87544..489514b437b 100644 --- a/mysql-test/suite/galera/r/query_cache.result +++ b/mysql-test/suite/galera/r/query_cache.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; # Execute FLUSH/RESET commands. # On node-1 diff --git a/mysql-test/suite/galera/r/rename.result b/mysql-test/suite/galera/r/rename.result index a7ec431657b..3ad715fa38c 100644 --- a/mysql-test/suite/galera/r/rename.result +++ b/mysql-test/suite/galera/r/rename.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; # # MDEV-8598 : Failed MySQL DDL commands and Galera replication # diff --git a/mysql-test/suite/galera/r/rpl_row_annotate.result b/mysql-test/suite/galera/r/rpl_row_annotate.result index 23de06f015b..61fa2bc286c 100644 --- a/mysql-test/suite/galera/r/rpl_row_annotate.result +++ b/mysql-test/suite/galera/r/rpl_row_annotate.result @@ -1,9 +1,15 @@ +connection node_2; +connection node_1; # On node_2 connection node_2; +SET GLOBAL wsrep_on=OFF; RESET MASTER; +SET GLOBAL wsrep_on=ON; # On node_1 connection node_1; +SET GLOBAL wsrep_on=OFF; RESET MASTER; +SET GLOBAL wsrep_on=ON; CREATE TABLE t1(i INT)ENGINE=INNODB; INSERT INTO t1 VALUES(1); DELETE FROM t1 WHERE i = 1; @@ -68,6 +74,4 @@ mysqld-bin.000001 # Table_map 2 # table_id: # (test.t1) mysqld-bin.000001 # Delete_rows_v1 2 # table_id: # flags: STMT_END_F mysqld-bin.000001 # Xid 2 # COMMIT /* xid= */ DROP TABLE t1; -disconnect node_2; -disconnect node_1; # End of test diff --git a/mysql-test/suite/galera/r/sql_log_bin.result b/mysql-test/suite/galera/r/sql_log_bin.result index c175a0a0e7a..6efd70ca8b8 100644 --- a/mysql-test/suite/galera/r/sql_log_bin.result +++ b/mysql-test/suite/galera/r/sql_log_bin.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; # On node_1 connection node_1; diff --git a/mysql-test/suite/galera/r/unique_key.result b/mysql-test/suite/galera/r/unique_key.result index 9f1fc858389..bb7e22014d9 100644 --- a/mysql-test/suite/galera/r/unique_key.result +++ b/mysql-test/suite/galera/r/unique_key.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; # # MDEV#5552 Deadlock when inserting NULL column value in column with # UNIQUE index diff --git a/mysql-test/suite/galera/r/view.result b/mysql-test/suite/galera/r/view.result index f8da811f9cc..45d5b422f3f 100644 --- a/mysql-test/suite/galera/r/view.result +++ b/mysql-test/suite/galera/r/view.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; # # MDEV-7222: Cluster Node Crash at CREATE DEFINER statement # diff --git a/mysql-test/suite/galera/r/wsrep_trx_fragment_size_non_sr.result b/mysql-test/suite/galera/r/wsrep_trx_fragment_size_non_sr.result new file mode 100644 index 00000000000..0e8a4088104 --- /dev/null +++ b/mysql-test/suite/galera/r/wsrep_trx_fragment_size_non_sr.result @@ -0,0 +1,25 @@ +connection node_2; +connection node_1; +SELECT variable_value FROM information_schema.session_variables +WHERE variable_name = 'wsrep_trx_fragment_size'; +variable_value +0 +SET SESSION wsrep_trx_fragment_size = 0; +SET SESSION wsrep_trx_fragment_size = 123; +ERROR 42000: Variable 'wsrep_trx_fragment_size' can't be set to the value of '123' +SHOW WARNINGS; +Level Code Message +Warning 1231 Cannot set 'wsrep_trx_fragment_size' to a value other than 0 because the wsrep_provider does not support streaming replication. +Error 1231 Variable 'wsrep_trx_fragment_size' can't be set to the value of '123' +SELECT variable_value FROM information_schema.global_variables +WHERE variable_name = 'wsrep_trx_fragment_size'; +variable_value +0 +SET GLOBAL wsrep_trx_fragment_size = 0; +SET GLOBAL wsrep_trx_fragment_size = 123; +ERROR 42000: Variable 'wsrep_trx_fragment_size' can't be set to the value of '123' +SHOW WARNINGS; +Level Code Message +Warning 1231 Cannot set 'wsrep_trx_fragment_size' to a value other than 0 because the wsrep_provider does not support streaming replication. +Error 1231 Variable 'wsrep_trx_fragment_size' can't be set to the value of '123' +SET GLOBAL wsrep_trx_fragment_size = default; diff --git a/mysql-test/suite/galera/r/wsrep_trx_fragment_size_sr.result b/mysql-test/suite/galera/r/wsrep_trx_fragment_size_sr.result new file mode 100644 index 00000000000..25e7d2dd54c --- /dev/null +++ b/mysql-test/suite/galera/r/wsrep_trx_fragment_size_sr.result @@ -0,0 +1,13 @@ +SELECT variable_value FROM information_schema.session_variables +WHERE variable_name = 'wsrep_trx_fragment_size'; +variable_value +0 +SET SESSION wsrep_trx_fragment_size = 0; +SET SESSION wsrep_trx_fragment_size = 123; +SELECT variable_value FROM information_schema.global_variables +WHERE variable_name = 'wsrep_trx_fragment_size'; +variable_value +0 +SET GLOBAL wsrep_trx_fragment_size = 0; +SET GLOBAL wsrep_trx_fragment_size = 123; +SET GLOBAL wsrep_trx_fragment_size = default; diff --git a/mysql-test/suite/galera/t/GAL-419.test b/mysql-test/suite/galera/t/GAL-419.test index e50b948bf35..07abcbcc47b 100644 --- a/mysql-test/suite/galera/t/GAL-419.test +++ b/mysql-test/suite/galera/t/GAL-419.test @@ -5,11 +5,11 @@ --source include/galera_cluster.inc --source include/big_test.inc ---connection node_2 +--connection node_1 SET SESSION wsrep_sync_wait = 0; --source include/kill_galera.inc ---connection node_1 +--connection node_2 SET SESSION wsrep_sync_wait = 0; --source include/kill_galera.inc diff --git a/mysql-test/suite/galera/t/GCF-1081.test b/mysql-test/suite/galera/t/GCF-1081.test new file mode 100644 index 00000000000..8296c55f1b6 --- /dev/null +++ b/mysql-test/suite/galera/t/GCF-1081.test @@ -0,0 +1,72 @@ +# +# GCF-1081 - Assertion `!thd->sp_runtime_ctx` +# +# Test replaying of stored procedures +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc +--source include/galera_have_debug_sync.inc + +--connection node_1 + +--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'` + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 0), (3, 0); + +DELIMITER |; +CREATE PROCEDURE proc_update () +BEGIN + UPDATE t1 SET f2 = 1 where f1 > 0; +END| +DELIMITER ;| + +# Block the SP +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--let $galera_sync_point = commit_monitor_master_enter_sync +--source include/galera_set_sync_point.inc + +--connection node_1 +--send CALL proc_update (); + +# Wait until SP is blocked +--connection node_1a +SET SESSION wsrep_sync_wait = 0; +--source include/galera_wait_sync_point.inc + +# Issue a conflicting insert on node #2 +--connection node_1a +SET GLOBAL DEBUG = 'd,sync.wsrep_before_BF_victim_unlock'; + +--connection node_2 +--send INSERT INTO t1 VALUES (2, 2); + +# Wait until it BF aborts the SP +--connection node_1a +SET SESSION DEBUG_SYNC = 'now WAIT_FOR sync.wsrep_before_BF_victim_unlock_reached'; +SET GLOBAL DEBUG = ''; + +# Unblock the SP +--connection node_1a +--source include/galera_clear_sync_point.inc +--source include/galera_signal_sync_point.inc + +--connection node_2 +--reap +SELECT * FROM t1; + +# SP succeeds +--connection node_1 +--reap +SELECT * FROM t1; + +# wsrep_local_replays has increased by 1 +--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'` +--disable_query_log +--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old AS wsrep_local_replays; +--enable_query_log + +DROP PROCEDURE proc_update; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/GCF-939.test b/mysql-test/suite/galera/t/GCF-939.test new file mode 100644 index 00000000000..95d8ce9b22b --- /dev/null +++ b/mysql-test/suite/galera/t/GCF-939.test @@ -0,0 +1,25 @@ +# +# GCF-939 Avoid creation of GRA log files when applier is successfull +# + +--source include/galera_cluster.inc + +--exec rm -rf $MYSQLTEST_VARDIR/mysqld.2/data/GRA_*.log + +--connection node_1 +--error ER_BAD_TABLE_ERROR +DROP TABLE t1; + +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +# Expect only one GRA_*.log file +--replace_regex /GRA_.+\.log/GRA_.log/ +--list_files $MYSQLTEST_VARDIR/mysqld.2/data GRA_*.log + +DROP TABLE t1; +CALL mtr.add_suppression("Ignoring error 'Unknown table 'test.t1'' on query"); +--connection node_2 +CALL mtr.add_suppression("Error 'Unknown table 'test.t1'' on query"); + + diff --git a/mysql-test/suite/galera/t/MW-284.test b/mysql-test/suite/galera/t/MW-284.test index 5e17baa1bdb..b2245eace84 100644 --- a/mysql-test/suite/galera/t/MW-284.test +++ b/mysql-test/suite/galera/t/MW-284.test @@ -63,7 +63,9 @@ CALL mtr.add_suppression('failed registering on master'); CALL mtr.add_suppression('You need to use --log-bin to make --binlog-format work'); --connection node_1 +set global wsrep_on=OFF; RESET MASTER; +set global wsrep_on=OFF; CALL mtr.add_suppression('WSREP: Last Applied Action message in non-primary configuration from member'); --connection node_2 diff --git a/mysql-test/suite/galera/t/MW-292.test b/mysql-test/suite/galera/t/MW-292.test index ecb1273759e..9580d53d85c 100644 --- a/mysql-test/suite/galera/t/MW-292.test +++ b/mysql-test/suite/galera/t/MW-292.test @@ -9,7 +9,7 @@ --source include/galera_cluster.inc --source include/have_innodb.inc --source include/have_debug_sync.inc ---source suite/galera/include/galera_have_debug_sync.inc +--source include/galera_have_debug_sync.inc --let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'` @@ -25,37 +25,51 @@ START TRANSACTION; UPDATE t1 SET f2 = 'b' WHERE f1 = 1; SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE; -# Block the commit +# Block the applier on node #1 and issue a conflicting update on node #2 --connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 ---let $galera_sync_point = commit_monitor_enter_sync +SET SESSION wsrep_sync_wait=0; +--let $galera_sync_point = apply_monitor_slave_enter_sync --source include/galera_set_sync_point.inc ---connection node_1 ---send COMMIT; +--connection node_2 +UPDATE t1 SET f2 = 'c' WHERE f1 = 2; -# Wait until commit is blocked --connection node_1a -SET SESSION wsrep_sync_wait = 0; --source include/galera_wait_sync_point.inc +--source include/galera_clear_sync_point.inc -# Issue a conflicting update on node #2 ---connection node_2 -UPDATE t1 SET f2 = 'c' WHERE f1 = 2; +# Block the commit, send the COMMIT and wait until it gets blocked -# Wait for both transactions to be blocked ---connection node_1a ---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Update_rows_log_event::find_row%'; ---source include/wait_condition.inc +--let $galera_sync_point = commit_monitor_master_enter_sync +--source include/galera_set_sync_point.inc ---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'init' AND INFO = 'COMMIT'; ---source include/wait_condition.inc +--connection node_1 +--send COMMIT -# Unblock the commit --connection node_1a + +--let $galera_sync_point = apply_monitor_slave_enter_sync commit_monitor_master_enter_sync +--source include/galera_wait_sync_point.inc --source include/galera_clear_sync_point.inc + +# Let the conflicting UPDATE proceed and wait until it hits abort_trx_end. +# The victim transaction still sits in commit_monitor_master_sync_point. + +--let $galera_sync_point = abort_trx_end +--source include/galera_set_sync_point.inc +--let $galera_sync_point = apply_monitor_slave_enter_sync +--source include/galera_signal_sync_point.inc +--let $galera_sync_point = abort_trx_end commit_monitor_master_enter_sync +--source include/galera_wait_sync_point.inc + +# Let the transactions proceed +--source include/galera_clear_sync_point.inc +--let $galera_sync_point = abort_trx_end +--source include/galera_signal_sync_point.inc +--let $galera_sync_point = commit_monitor_master_enter_sync --source include/galera_signal_sync_point.inc -# Commit succeeds via replay +# Commit succeeds --connection node_1 --reap diff --git a/mysql-test/suite/galera/t/MW-328A.test b/mysql-test/suite/galera/t/MW-328A.test index 4d6e1ea3625..268ce28f734 100644 --- a/mysql-test/suite/galera/t/MW-328A.test +++ b/mysql-test/suite/galera/t/MW-328A.test @@ -3,8 +3,13 @@ # # -# Attempt to insert into t2 and check if insert actually inserted rows if -# a success was reported. +# test phase 1 is not deterministic +# +# Here we attempt to insert into t2 and check if insert actually +# inserted rows if a success was reported. +# +# However, deadlocks may or may not happen in this test execution +# it all depends on timing. # --source include/galera_cluster.inc @@ -24,7 +29,7 @@ while ($count) { TRUNCATE TABLE t2; - --error 0,1213 + --error 0,ER_LOCK_DEADLOCK INSERT IGNORE INTO t2 SELECT f2 FROM t1; if ($mysql_errno != 1213) { --inc $successes @@ -43,14 +48,31 @@ while ($count) --enable_query_log + +--source suite/galera/t/MW-328-footer.inc + # -# Check that the test produced both deadlocks and successes +# Test phase 2 is deterministic +# Here we generate a sure conflict in node 1 and verify that +# insert failed in both nodes # +--connection node_1 +CREATE TABLE t1 (i int primary key, j int) engine=innodb; +INSERT INTO t1 values (1,0); ---disable_query_log ---eval SELECT $successes > 0 AS have_successes ---eval SELECT $deadlocks > 0 AS have_deadlocks ---enable_query_log +BEGIN; +UPDATE t1 SET j=1 WHERE i=1; +--connection node_2 +UPDATE t1 SET j=2 WHERE i=1; ---source suite/galera/t/MW-328-footer.inc +--connection node_1 +--error ER_LOCK_DEADLOCK +COMMIT; + +SELECT * FROM t1; +--connection node_2 +SELECT * FROM t1; +--connection node_1 + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/MW-329.test b/mysql-test/suite/galera/t/MW-329.test index 5baa4d14966..78755fc3b42 100644 --- a/mysql-test/suite/galera/t/MW-329.test +++ b/mysql-test/suite/galera/t/MW-329.test @@ -11,11 +11,6 @@ CREATE TABLE t1 (f1 INTEGER, f2 CHAR(20) DEFAULT 'abc') ENGINE=InnoDB; # We start with a populated table INSERT INTO t1 (f1) VALUES (1),(65535); -# Clear the wsrep_local_replays counter - -FLUSH STATUS; -SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'; - # # Run concurrent INSERTs # @@ -42,8 +37,9 @@ DELIMITER ;| # --connection node_2 -CALL mtr.add_suppression("WSREP: Failed to report last committed .*"); ---let $count = 200 +--let $count = 10 +--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'` + while ($count) { --let $signature = `SELECT LEFT(MD5(RAND()), 10)` @@ -57,14 +53,28 @@ while ($count) --die ROW_COUNT() = 0 } } - --dec $count + + # + # Ensure at least one replay happens + # + + --let $wsrep_replays = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'` + --disable_query_log + if (`SELECT $wsrep_replays - $wsrep_local_replays_old > 0`) { + --dec $count + } + --enable_query_log } # # Confirm that some transaction replays occurred # -SELECT VARIABLE_VALUE > 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'; +--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'` +--disable_query_log +--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old > 0 AS wsrep_local_replays; +--enable_query_log + # # Terminate the stored procedure diff --git a/mysql-test/suite/galera/t/MW-336.test b/mysql-test/suite/galera/t/MW-336.test index 8cd363aa019..8ccd48fb35f 100644 --- a/mysql-test/suite/galera/t/MW-336.test +++ b/mysql-test/suite/galera/t/MW-336.test @@ -10,7 +10,7 @@ CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; --connection node_1 SET GLOBAL wsrep_slave_threads = 10; SET GLOBAL wsrep_slave_threads = 1; ---let $wait_condition = SELECT COUNT(*) = 11 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%'); +--let $wait_condition = SELECT COUNT(*) = 12 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%'); --source include/wait_condition.inc --connection node_2 @@ -18,11 +18,11 @@ INSERT INTO t1 VALUES (1); --connection node_1 SET GLOBAL wsrep_slave_threads = 10; ---let $wait_condition = SELECT COUNT(*) = 11 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%'); +--let $wait_condition = SELECT COUNT(*) = 12 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%'); --source include/wait_condition.inc SET GLOBAL wsrep_slave_threads = 20; ---let $wait_condition = SELECT COUNT(*) = 21 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%'); +--let $wait_condition = SELECT COUNT(*) = 22 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%'); --source include/wait_condition.inc SET GLOBAL wsrep_slave_threads = 1; @@ -40,7 +40,7 @@ INSERT INTO t1 VALUES (9); --connection node_1 ---let $wait_condition = SELECT COUNT(*) = 12 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%'); +--let $wait_condition = SELECT COUNT(*) = 13 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%'); --source include/wait_condition.inc SET GLOBAL wsrep_slave_threads = 10; @@ -60,7 +60,7 @@ INSERT INTO t1 VALUES (19); INSERT INTO t1 VALUES (20); --connection node_1 ---let $wait_condition = SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%'); +--let $wait_condition = SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%'); --source include/wait_condition.inc SET GLOBAL wsrep_slave_threads = 1; diff --git a/mysql-test/suite/galera/t/MW-360-master.opt b/mysql-test/suite/galera/t/MW-360-master.opt new file mode 100644 index 00000000000..e51c49c3808 --- /dev/null +++ b/mysql-test/suite/galera/t/MW-360-master.opt @@ -0,0 +1,2 @@ +--gtid-domain-id=1 --log-bin --log-slave-updates + diff --git a/mysql-test/suite/galera/t/MW-360.test b/mysql-test/suite/galera/t/MW-360.test new file mode 100644 index 00000000000..b776631cfff --- /dev/null +++ b/mysql-test/suite/galera/t/MW-360.test @@ -0,0 +1,100 @@ +# +# MW-360 DROP TABLE containing temporary tables results in binlog divergence +# + +--source include/galera_cluster.inc +--source include/have_binlog_format_row.inc + +--connection node_1 +SET GLOBAL wsrep_on=OFF; +RESET MASTER; +SET GLOBAL wsrep_on=ON; + +--connection node_2 +SET GLOBAL wsrep_on=OFF; +RESET MASTER; +SET GLOBAL wsrep_on=ON; + +--connection node_1 + +# +# Straightforward temporary table +# + +CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +DROP TABLE t1; + +--let $local_uuid = `SELECT LEFT(@@global.gtid_executed, 36)` + +# +# A mix of normal and temporary tables +# + +# Temp table first, normal table second + +CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t2 VALUES (2); + +DROP TABLE t1, t2; + +# Normal table first, temporary table second + +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +CREATE TEMPORARY TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t2 VALUES (2); + +DROP TABLE t1, t2; + +# Temporary table first, normal table second, temp table third + +CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t2 VALUES (2); + +CREATE TEMPORARY TABLE t3 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t3 VALUES (3); + +DROP TABLE t1, t2, t3; + +# Normal table first, temporary table second, normal table third + +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +CREATE TEMPORARY TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t2 VALUES (2); + +CREATE TABLE t3 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t3 VALUES (3); + +DROP TABLE t1, t2, t3; + +# +# A temporary table masking a normal one +# + +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +CREATE TEMPORARY TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (2); + +DROP TABLE t1; +DROP TABLE t1; + +--connection node_2 +--let $gtid_executed_node2 = `SELECT @@global.gtid_executed;` + +--connection node_1 +--disable_query_log +# Node 1 has extra GTID set generated by the temporary table drop +--eval SELECT GTID_SUBSET('$gtid_executed_node2', @@global.gtid_executed) AS gtid_executed_equal; +--enable_query_log diff --git a/mysql-test/suite/galera/t/MW-369.inc b/mysql-test/suite/galera/t/MW-369.inc index 5fd9ef150ae..71df979d6ba 100644 --- a/mysql-test/suite/galera/t/MW-369.inc +++ b/mysql-test/suite/galera/t/MW-369.inc @@ -24,7 +24,6 @@ --connection node_1 SET AUTOCOMMIT=ON; START TRANSACTION; - --eval $mw_369_parent_query # @@ -51,7 +50,7 @@ SET SESSION wsrep_sync_wait = 0; --source include/galera_wait_sync_point.inc --source include/galera_clear_sync_point.inc ---let $galera_sync_point = local_monitor_enter_sync +--let $galera_sync_point = local_monitor_master_enter_sync --source include/galera_set_sync_point.inc --connection node_1 @@ -61,7 +60,7 @@ SET SESSION wsrep_sync_wait = 0; # Wait until both sync points have been reached # --connection node_1a ---let $galera_sync_point = apply_monitor_slave_enter_sync local_monitor_enter_sync +--let $galera_sync_point = apply_monitor_slave_enter_sync local_monitor_master_enter_sync --source include/galera_wait_sync_point.inc # @@ -70,6 +69,6 @@ SET SESSION wsrep_sync_wait = 0; --let $galera_sync_point = apply_monitor_slave_enter_sync --source include/galera_signal_sync_point.inc ---let $galera_sync_point = local_monitor_enter_sync +--let $galera_sync_point = local_monitor_master_enter_sync --source include/galera_signal_sync_point.inc --source include/galera_clear_sync_point.inc diff --git a/mysql-test/suite/galera/t/MW-369.test b/mysql-test/suite/galera/t/MW-369.test index 720d6daf518..99242224864 100644 --- a/mysql-test/suite/galera/t/MW-369.test +++ b/mysql-test/suite/galera/t/MW-369.test @@ -24,7 +24,6 @@ --source include/galera_cluster.inc --source include/have_innodb.inc --source include/have_debug_sync.inc ---source suite/galera/include/galera_have_debug_sync.inc CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, diff --git a/mysql-test/suite/galera/t/MW-388.test b/mysql-test/suite/galera/t/MW-388.test index de1ac52bf3e..ab15fda64eb 100644 --- a/mysql-test/suite/galera/t/MW-388.test +++ b/mysql-test/suite/galera/t/MW-388.test @@ -2,7 +2,6 @@ --source include/have_innodb.inc --source include/have_debug.inc --source include/have_debug_sync.inc - --connection node_1 CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) Engine=InnoDB; diff --git a/mysql-test/suite/galera/t/MW-402.test b/mysql-test/suite/galera/t/MW-402.test index 36b691c6295..4b83e25dc50 100644 --- a/mysql-test/suite/galera/t/MW-402.test +++ b/mysql-test/suite/galera/t/MW-402.test @@ -1,6 +1,6 @@ --source include/galera_cluster.inc --source include/have_innodb.inc ---source suite/galera/include/galera_have_debug_sync.inc +--source include/galera_have_debug_sync.inc # # we must open connection node_1a here, MW-369.inc will use it later @@ -135,7 +135,6 @@ SELECT * FROM c; DROP TABLE c; DROP TABLE p; - # # CASCADE DELETE tests with two parent tables # Here we cause cascaded operation on child table through @@ -151,10 +150,11 @@ DROP TABLE p; CREATE TABLE p1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; CREATE TABLE p2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; -CREATE TABLE c (f1 INTEGER PRIMARY KEY, p1_id INTEGER, p2_id INTEGER, f2 INTEGER, - CONSTRAINT fk_1 FOREIGN KEY (p1_id) REFERENCES p1 (f1) ON DELETE CASCADE, +CREATE TABLE c (f1 INTEGER PRIMARY KEY, p1_id INTEGER, p2_id INTEGER, + f2 INTEGER, + CONSTRAINT fk_1 FOREIGN KEY (p1_id) REFERENCES p1 (f1) + ON DELETE CASCADE, CONSTRAINT fk_2 FOREIGN KEY (p2_id) REFERENCES p2 (f1)); - INSERT INTO p1 VALUES (1, 0); INSERT INTO p2 VALUES (1, 0); @@ -171,7 +171,51 @@ INSERT INTO c VALUES (1, 1, 1, 0); --connection node_1 --reap -# same as previous, but statements in different order +--connection node_2 +SELECT * FROM p1; +SELECT * FROM p2; +SELECT * FROM c; + +DROP TABLE c; +DROP TABLE p1; +DROP TABLE p2; + +# +# CASCADE DELETE tests with two parent tables +# Here we cause cascaded operation on child table through +# one parent table and issue other delete operation through the +# other parent table. The cascade progresses to same child table row where +# we should see the conflict to happen +# +# As a result, the update on p2 should fail +# +--connection node_1 + +CREATE TABLE p1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; +CREATE TABLE p2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; +CREATE TABLE c (f1 INTEGER PRIMARY KEY, p1_id INTEGER, p2_id INTEGER, + f2 INTEGER, + CONSTRAINT fk_1 FOREIGN KEY (p1_id) REFERENCES p1 (f1) + ON DELETE CASCADE, + CONSTRAINT fk_2 FOREIGN KEY (p2_id) REFERENCES p2 (f1) + ON DELETE CASCADE); + +INSERT INTO p1 VALUES (1, 0); +INSERT INTO p2 VALUES (1, 0); + +INSERT INTO c VALUES (1, 1, 1, 0); + +--let $mw_369_parent_query = DELETE FROM p2 WHERE f1=1 +--let $mw_369_child_query = DELETE FROM p1 WHERE f1=1 + +--connection node_1a +--source MW-369.inc + +# Commit succeeds +--connection node_1 +--error ER_LOCK_DEADLOCK +--reap + --connection node_2 SELECT * FROM p1; SELECT * FROM p2; diff --git a/mysql-test/suite/galera/t/MW-416.test b/mysql-test/suite/galera/t/MW-416.test index df4fa35abc7..d4dd98c0fcf 100644 --- a/mysql-test/suite/galera/t/MW-416.test +++ b/mysql-test/suite/galera/t/MW-416.test @@ -1,12 +1,10 @@ --source include/galera_cluster.inc --source include/have_innodb.inc ---source include/wait_until_ready.inc - CREATE USER 'userMW416'@'localhost'; GRANT SELECT, INSERT, UPDATE ON test.* TO 'userMW416'@'localhost'; -SHOW GLOBAL STATUS LIKE 'wsrep_replicated'; +--let $wsrep_replicated_before = `SELECT variable_value FROM information_schema.global_status WHERE variable_name = 'wsrep_replicated'` --connect userMW416, localhost, userMW416,, test, $NODE_MYPORT_1 --connection userMW416 @@ -69,16 +67,18 @@ DROP EVENT ev; DROP FUNCTION fun1; --error 1044,1142,1227,1370 DROP INDEX idx ON t0; ---error 1044,1142,1227,1370,1064 -DROP LOGFILE GROUP lfg; +# DROP LOGFILE is not in MariaDB +#--error 1044,1142,1227,1370 +#DROP LOGFILE GROUP lfg; --error 1044,1142,1227,1370 DROP PROCEDURE proc1; --error 1044,1142,1227,1370 DROP SERVEr srv; --error 1044,1142,1227,1370 DROP TABLE t0; ---error 1044,1142,1227,1370,1064 -DROP TABLESPACE tblspc; +# DROP TABLESPACE is not in MariaDB +#--error 1044,1142,1227,1370 +#DROP TABLESPACE tblspc; --error 1044,1142,1227,1360,1370 DROP TRIGGER trg; --error 1044,1142,1227,1370 @@ -93,8 +93,9 @@ TRUNCATE TABLE t0; # DCL # account management ---error 1044,1142,1227,1370,1064 -ALTER USER myuser PASSWORD EXPIRE; +# PASSWORD EXPIRE is not in MariaDB +#--error 1044,1142,1227,1370 +#ALTER USER myuser PASSWORD EXPIRE; --error 1044,1142,1227,1370 CREATE USER myuser IDENTIFIED BY 'pass'; --error 1044,1142,1227,1370 @@ -131,4 +132,7 @@ UNINSTALL PLUGIN plg; --connection node_1 DROP USER 'userMW416'@'localhost'; SHOW DATABASES; -SHOW GLOBAL STATUS LIKE 'wsrep_replicated'; +--let $wsrep_replicated_after = `SELECT variable_value FROM information_schema.global_status WHERE variable_name = 'wsrep_replicated'` +--disable_query_log +--eval SELECT $wsrep_replicated_after - $wsrep_replicated_before AS wsrep_replicated_after_diff +--enable_query_log diff --git a/mysql-test/suite/galera/t/MW-86-master.opt b/mysql-test/suite/galera/t/MW-86-master.opt new file mode 100644 index 00000000000..8a755e98b00 --- /dev/null +++ b/mysql-test/suite/galera/t/MW-86-master.opt @@ -0,0 +1 @@ +--log-bin --log-slave-updates diff --git a/mysql-test/suite/galera/t/MW-86-wait1.test b/mysql-test/suite/galera/t/MW-86-wait1.test index 6c0982ad8b3..aee5a0b2486 100644 --- a/mysql-test/suite/galera/t/MW-86-wait1.test +++ b/mysql-test/suite/galera/t/MW-86-wait1.test @@ -6,13 +6,15 @@ --source include/galera_cluster.inc --source include/have_binlog_format_row.inc --source include/have_debug_sync.inc +SET @orig_debug=@@debug; --connection node_2 # Make sure no signals have been leftover from previous tests to surprise us. SELECT @@debug_sync; +set debug_sync='RESET'; SET SESSION wsrep_sync_wait = 1; -SET GLOBAL debug = "+d,sync.wsrep_apply_cb"; +SET GLOBAL debug_dbug = "+d,sync.wsrep_apply_cb"; --connection node_1 CREATE TABLE t_wait1 (f1 INTEGER) ENGINE=InnoDB; @@ -90,17 +92,16 @@ SHOW WARNINGS; --enable_result_log # Unblock the background INSERT and remove the sync point. -SET GLOBAL debug = "-d,sync.wsrep_apply_cb"; -SET SESSION debug_sync = "now SIGNAL signal.wsrep_apply_cb"; +#SET GLOBAL debug_dbug = "-d,sync.wsrep_apply_cb"; +SET GLOBAL debug_dbug = @orig_debug; +SET SESSION debug_sync = "now SIGNAL signal.wsrep_apply_cb"; +SET debug_sync='RESET'; SET SESSION wsrep_sync_wait = default; # This will wait for the background INSERT to complete before we quit # from the test. DROP TABLE t_wait1; -SET GLOBAL debug = NULL; -SET debug_sync='RESET'; - # Make sure no pending signals are leftover to surprise subsequent tests. SELECT @@debug_sync; diff --git a/mysql-test/suite/galera/t/MW-86-wait8.test b/mysql-test/suite/galera/t/MW-86-wait8.test index 65e612c5c8e..c40cd8b77c7 100644 --- a/mysql-test/suite/galera/t/MW-86-wait8.test +++ b/mysql-test/suite/galera/t/MW-86-wait8.test @@ -4,13 +4,14 @@ --source include/galera_cluster.inc --source include/have_binlog_format_row.inc --source include/have_debug_sync.inc +SET @orig_debug=@@debug; --connection node_2 # Make sure no signals have been leftover from previous tests to surprise us. SELECT @@debug_sync; SET SESSION wsrep_sync_wait = 8; -SET GLOBAL debug = "+d,sync.wsrep_apply_cb"; +SET GLOBAL debug_dbug = "+d,sync.wsrep_apply_cb"; --connection node_1 CREATE TABLE t_wait8 (f1 INTEGER) ENGINE=InnoDB; @@ -112,8 +113,11 @@ SHOW WARNINGS; --enable_query_log # Unblock the background INSERT and remove the sync point. -SET GLOBAL debug = "-d,sync.wsrep_apply_cb"; +#SET GLOBAL debug = "-d,sync.wsrep_apply_cb"; +SET GLOBAL debug_dbug = @orig_debug; + SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; +SET debug_sync='RESET'; SET SESSION wsrep_sync_wait = default; @@ -121,8 +125,5 @@ SET SESSION wsrep_sync_wait = default; # from the test. DROP TABLE t_wait8; -SET GLOBAL debug = NULL; -SET debug_sync='RESET'; - # Make sure no pending signals are leftover to surprise subsequent tests. SELECT @@debug_sync; diff --git a/mysql-test/suite/galera/t/MW-86.test b/mysql-test/suite/galera/t/MW-86.test new file mode 100644 index 00000000000..2614eb89504 --- /dev/null +++ b/mysql-test/suite/galera/t/MW-86.test @@ -0,0 +1,193 @@ +--source include/galera_cluster.inc +--source include/have_binlog_format_row.inc + +# +# Test 1: SHOW commands no longer obey wsrep_sync_wait = 1 +# + +--connection node_2 +SET SESSION wsrep_sync_wait = 1; +SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; +--disable_result_log + +--connection node_1 +CREATE DATABASE db1; +CREATE TABLE bar (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO bar VALUES (1); + +--connection node_2 +SHOW BINARY LOGS; + +SHOW BINLOG EVENTS; + +--error ER_NO_SUCH_TABLE +SHOW COLUMNS FROM t1; + +--error 0 +SHOW CREATE DATABASE db1; + +--error ER_EVENT_DOES_NOT_EXIST +SHOW CREATE EVENT e1; + +--error ER_SP_DOES_NOT_EXIST +SHOW CREATE FUNCTION f1; + +--error ER_SP_DOES_NOT_EXIST +SHOW CREATE PROCEDURE p1; + +--error ER_NO_SUCH_TABLE +SHOW CREATE TABLE t1; + +--error ER_TRG_DOES_NOT_EXIST +SHOW CREATE TRIGGER tr1; + +--error ER_NO_SUCH_TABLE +SHOW CREATE VIEW v1; + +SHOW DATABASES; + +SHOW ENGINE InnoDB STATUS; + +--error ER_SP_DOES_NOT_EXIST +SHOW FUNCTION CODE f1; + +SHOW FUNCTION STATUS; + +SHOW GRANTS FOR 'root'@'localhost'; + +--error ER_NO_SUCH_TABLE +SHOW INDEX FROM t1; + +SHOW OPEN TABLES; + +--error ER_SP_DOES_NOT_EXIST +SHOW PROCEDURE CODE p1; + +SHOW PROCEDURE STATUS; + +SHOW PRIVILEGES; + +SHOW STATUS LIKE 'wsrep_cluster_size'; + +SHOW TABLE STATUS; + +SHOW TABLES; + +SHOW TRIGGERS; + +SHOW GLOBAL VARIABLES LIKE 'foo_bar'; + +--error 0 +SHOW WARNINGS; + +SET GLOBAL DEBUG = ""; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; + +SET SESSION wsrep_sync_wait = 8; +DROP DATABASE db1; + + +# +# Test 2: SHOW commands now obey wsrep_sync_wait = 8 +# + +--connection node_2 +--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options` +SET GLOBAL wsrep_provider_options = "repl.causal_read_timeout=PT0.1S"; +SET SESSION wsrep_sync_wait = 8; +SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; + +--connection node_1 +CREATE TABLE q (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO q VALUES (1); + +--connection node_2 +--error ER_LOCK_WAIT_TIMEOUT +SHOW BINARY LOGS; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW BINLOG EVENTS; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW COLUMNS FROM t1; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW CREATE DATABASE db1; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW CREATE EVENT e1; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW CREATE FUNCTION f1; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW CREATE PROCEDURE p1; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW CREATE TABLE t1; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW CREATE TRIGGER tr1; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW CREATE VIEW v1; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW DATABASES; + +--error 0 +SHOW ENGINE InnoDB STATUS; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW FUNCTION CODE f1; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW FUNCTION STATUS; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW GRANTS FOR 'root'@'localhost'; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW INDEX FROM t1; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW OPEN TABLES; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW PROCEDURE CODE p1; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW PROCEDURE STATUS; + +--error 0 +SHOW PRIVILEGES; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW STATUS LIKE 'wsrep_cluster_size'; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW TABLE STATUS; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW TABLES; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW TRIGGERS; + +--error ER_LOCK_WAIT_TIMEOUT +SHOW GLOBAL VARIABLES LIKE 'foo_bar'; + +--error 0 +SHOW WARNINGS; + +SET GLOBAL DEBUG = ""; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; + +--disable_query_log +--eval SET GLOBAL wsrep_provider_options = "$wsrep_provider_options_orig" + +SET SESSION wsrep_sync_wait = 15; +SET GLOBAL debug_dbug=NULL; +SET debug_sync='RESET'; +DROP TABLE q, bar; +SELECT @@debug_sync;
\ No newline at end of file diff --git a/mysql-test/suite/galera/t/disabled.def b/mysql-test/suite/galera/t/disabled.def new file mode 100644 index 00000000000..43b652200d1 --- /dev/null +++ b/mysql-test/suite/galera/t/disabled.def @@ -0,0 +1,13 @@ +galera_wsrep_provider_unset_set : lp1379204 'Unsupported protocol downgrade: incremental data collection disabled. Expect abort.' +galera_kill_nochanges : mysql-wsrep#24 Galera server does not restart properly if killed +galera_toi_ddl_fk_insert : qa#39 galera_toi_ddl_fk_insert fails sporadically +galera_sst_xtrabackup-v2-options : SST Encryption does not work with xtrabackup 2.4.2 +#galera_autoinc_sst_xtrabackup : due to cert index preload, this test will never pass in current form (gcache.size=1) +GCF-574 : CTAS is not supported together with SR +galera_split_brain : is worked on with tracker GCF-998 +galera_sr_kill_all_pcrecovery : is worked on with tracker GCF-1068 +galera_var_notify_cmd : is worked on with tracker GCF-1071 +galera_gcache_recover_manytrx : is worked on with tracker GCF-1077 +GCF-1081 : tries to BF abort earlier trx, needs to be reimplemented +galera_bf_abort_group_commit : requires galera_sr_bf_abort.inc, probably needs reimplementation +galera_as_slave_gtid_replicate_do_db_cc : assertion diff --git a/mysql-test/suite/galera/t/galera_applier_ftwrl_table_alter-master.opt b/mysql-test/suite/galera/t/galera_applier_ftwrl_table_alter-master.opt index d8ecaacaa4c..6f688b39fd5 100644 --- a/mysql-test/suite/galera/t/galera_applier_ftwrl_table_alter-master.opt +++ b/mysql-test/suite/galera/t/galera_applier_ftwrl_table_alter-master.opt @@ -1 +1 @@ ---lock_wait_timeout=5 --innodb_lock_wait_timeout=5 --wait_timeout=5 +--lock_wait_timeout=5 --innodb_lock_wait_timeout=5 --wait_timeout=60 diff --git a/mysql-test/suite/galera/t/galera_as_master.test b/mysql-test/suite/galera/t/galera_as_master.test index 49f3c993256..1c439ffff63 100644 --- a/mysql-test/suite/galera/t/galera_as_master.test +++ b/mysql-test/suite/galera/t/galera_as_master.test @@ -64,4 +64,6 @@ RESET SLAVE ALL; CALL mtr.add_suppression('You need to use --log-bin to make --binlog-format work'); --connection node_1 +set global wsrep_on=OFF; RESET MASTER; +set global wsrep_on=ON; diff --git a/mysql-test/suite/galera/t/galera_as_master_gtid.test b/mysql-test/suite/galera/t/galera_as_master_gtid.test index 9db104b7cab..9be065e448b 100644 --- a/mysql-test/suite/galera/t/galera_as_master_gtid.test +++ b/mysql-test/suite/galera/t/galera_as_master_gtid.test @@ -27,10 +27,6 @@ INSERT INTO t1 VALUES(1); --eval SELECT '$effective_uuid' != @@global.server_uuid AS uuids_do_not_match; --enable_query_log ---replace_result $effective_uuid <effective_uuid> ---replace_regex /table_id: [0-9]+/table_id: #/ /xid=[0-9]+/xid=#/ -SHOW BINLOG EVENTS IN 'mysqld-bin.000002' FROM 120; - --connection node_2 INSERT INTO t1 VALUES(2); @@ -39,10 +35,6 @@ INSERT INTO t1 VALUES(2); --eval SELECT '$effective_uuid' = LEFT(@@global.gtid_executed, 36) AS uuids_match; --enable_query_log ---replace_result $effective_uuid <effective_uuid> ---replace_regex /table_id: [0-9]+/table_id: #/ /xid=[0-9]+/xid=#/ -SHOW BINLOG EVENTS IN 'mysqld-bin.000003' FROM 120; - --connection node_3 --let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; --source include/wait_condition.inc @@ -55,10 +47,6 @@ SHOW BINLOG EVENTS IN 'mysqld-bin.000003' FROM 120; --eval SELECT '$effective_uuid' = LEFT(@@global.gtid_executed, 36) AS uuids_match; --enable_query_log ---replace_result $effective_uuid <effective_uuid> ---replace_regex /table_id: [0-9]+/table_id: #/ /xid=[0-9]+/xid=#/ -SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 120; - --connection node_1 DROP TABLE t1; @@ -66,5 +54,17 @@ DROP TABLE t1; --let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; --source include/wait_condition.inc +--connection node_1 +--let $gtid_executed_node1 = `SELECT @@global.gtid_executed;` + +--connection node_2 +--disable_query_log +--eval SELECT '$gtid_executed_node1' = @@global.gtid_executed AS gtid_executed_equal +--enable_query_log +--connection node_3 +--disable_query_log +--eval SELECT '$gtid_executed_node1' = @@global.gtid_executed AS gtid_executed_equal +--enable_query_log + STOP SLAVE; RESET SLAVE ALL; diff --git a/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.test b/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.test index 23606d7ac4c..61c7eed6543 100644 --- a/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.test +++ b/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.test @@ -24,6 +24,8 @@ INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(2); --connection node_3 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc STOP SLAVE; --disable_query_log --eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_2, MASTER_AUTO_POSITION=1; diff --git a/mysql-test/suite/galera/t/galera_as_slave.test b/mysql-test/suite/galera/t/galera_as_slave.test index 849b75eadd1..144c0a4413d 100644 --- a/mysql-test/suite/galera/t/galera_as_slave.test +++ b/mysql-test/suite/galera/t/galera_as_slave.test @@ -5,18 +5,19 @@ # --source include/have_innodb.inc - -# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc ---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 --source include/galera_cluster.inc +# As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it +# we open the node_3 connection here +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 + --connection node_2 --disable_query_log ---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1; +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3; --enable_query_log START SLAVE; ---connection node_1 +--connection node_3 CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES(1); @@ -29,14 +30,14 @@ INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES (2); ---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_1 SELECT COUNT(*) = 2 FROM t1; INSERT INTO t1 VALUES (3); --connection node_2 SELECT COUNT(*) = 3 FROM t1; ---connection node_1 +--connection node_3 DROP TABLE t1; --connection node_2 @@ -46,5 +47,7 @@ DROP TABLE t1; STOP SLAVE; RESET SLAVE ALL; ---connection node_1 +--connection node_3 +SET GLOBAL wsrep_on=OFF; RESET MASTER; +SET GLOBAL wsrep_on=ON; diff --git a/mysql-test/suite/galera/t/galera_as_slave_autoinc.test b/mysql-test/suite/galera/t/galera_as_slave_autoinc.test index 59483d0591c..503d409cc57 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_autoinc.test +++ b/mysql-test/suite/galera/t/galera_as_slave_autoinc.test @@ -5,18 +5,19 @@ # --source include/have_innodb.inc - -# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc ---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 --source include/galera_cluster.inc +# As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it +# we open the node_3 connection here +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 + --connection node_2 --disable_query_log ---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1; +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3; --enable_query_log START SLAVE; ---connection node_1 +--connection node_3 ## ## Verify the correct operation of the auto-increment when @@ -62,14 +63,13 @@ select * from t1; show variables like 'binlog_format'; show variables like 'auto_increment_increment'; ---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 - +--connection node_1 select * from t1; show variables like 'binlog_format'; show variables like 'auto_increment_increment'; ---connection node_1 +--connection node_3 DROP TABLE t1; --connection node_2 @@ -79,5 +79,7 @@ DROP TABLE t1; STOP SLAVE; RESET SLAVE ALL; ---connection node_1 +--connection node_3 +SET GLOBAL wsrep_on=OFF; RESET MASTER; +SET GLOBAL wsrep_on=ON; diff --git a/mysql-test/suite/galera/t/galera_as_slave_gtid.test b/mysql-test/suite/galera/t/galera_as_slave_gtid.test index c2331a2ae05..3b0f191ad83 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_gtid.test +++ b/mysql-test/suite/galera/t/galera_as_slave_gtid.test @@ -8,18 +8,19 @@ # --source include/have_innodb.inc - -# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc ---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 --source include/galera_cluster.inc +# As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it +# we open the node_3 connection here +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 + --connection node_2 --disable_query_log ---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1; +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3; --enable_query_log START SLAVE; ---connection node_1 +--connection node_3 CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES(1); @@ -34,17 +35,21 @@ SELECT LENGTH(@@global.gtid_binlog_state) > 1; --source include/wait_condition.inc --disable_query_log + --eval SELECT '$gtid_binlog_state_node1' = @@global.gtid_binlog_state AS gtid_binlog_state_equal; +#--eval SELECT GTID_SUBSET('$gtid_executed_node1', @@global.gtid_executed) AS gtid_executed_equal; + --enable_query_log ---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_1 SELECT COUNT(*) = 1 FROM t1; --disable_query_log --eval SELECT '$gtid_binlog_state_node1' = @@global.gtid_binlog_state AS gtid_binlog_state_equal; +#--eval SELECT GTID_SUBSET('$gtid_executed_node1', @@global.gtid_executed) AS gtid_executed_equal; --enable_query_log ---connection node_1 +--connection node_3 DROP TABLE t1; # @@ -55,7 +60,7 @@ DROP TABLE t1; --sleep 1 ---connection node_3 +--connection node_1 --let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; --source include/wait_condition.inc diff --git a/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.cnf b/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.cnf new file mode 100644 index 00000000000..e0852c50c44 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.cnf @@ -0,0 +1,17 @@ +!include ../galera_2nodes_as_slave.cnf + +[mysqld] +#gtid-mode=ON +log-bin=master-bin +log-bin-index=master-bin +log-slave-updates +#enforce-gtid-consistency +binlog-format=ROW + +[mysqld.2] +replicate-do-db=test1 +replicate-wild-do-table=test1.% + +[mysqld.3] +replicate-do-db=test1 +replicate-wild-do-table=test1.% diff --git a/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.test b/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.test new file mode 100644 index 00000000000..7071d4901c8 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db.test @@ -0,0 +1,150 @@ +# +# Test Galera as a slave to a MySQL master using GTIDs +# + +--source include/have_innodb.inc +--source include/have_log_bin.inc + +# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--source include/galera_cluster.inc + +--connection node_1 +RESET MASTER; + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3 +SET global wsrep_on=OFF; +RESET MASTER; +SET global wsrep_on=ON; + +--connection node_2 +SET global wsrep_on=OFF; +RESET MASTER; +SET global wsrep_on=ON; +--disable_query_log +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_1, MASTER_USER='root'; +--enable_query_log +START SLAVE; + +--connection node_1 +CREATE SCHEMA test1; +CREATE SCHEMA test2; +USE test1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY,f2 CHAR(5) DEFAULT 'abc') ENGINE=InnoDB; +USE test2; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY,f2 CHAR(5) DEFAULT 'abc') ENGINE=InnoDB; + +# +# First , some autocommit stuff +# + +# Simple inserts + +INSERT INTO test1.t1 (f1) VALUES (1); +INSERT INTO test2.t1 (f1) VALUES (1); + +INSERT INTO test1.t1 (f1) VALUES (2); +INSERT INTO test2.t1 (f1) VALUES (2); + +INSERT INTO test1.t1 (f1) VALUES (3); +INSERT INTO test2.t1 (f1) VALUES (3); + +# Update that only covers test2.t1 + +UPDATE test2.t1 SET test2.t1.f2 = 'cde'; + +# Multi-table UPDATE + +UPDATE test1.t1, test2.t1 SET test1.t1.f2 = 'klm', test2.t1.f2 = 'xyz'; + +# Multi-table DELETE + +DELETE test1.t1, test2.t1 FROM test1.t1 INNER JOIN test2.t1 WHERE test1.t1.f1 = test2.t1.f1 AND test1.t1.f1 = 3; + +# +# Multi-statement transactions +# + +# Transaction which is not replicated at all + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO test2.t1 (f1) VALUES (999); +INSERT INTO test2.t1 (f1) VALUES (9999); +COMMIT; + +# Transaction that is completely replicated +START TRANSACTION; +INSERT INTO test1.t1 (f1) VALUES (111); +INSERT INTO test1.t1 (f1) VALUES (222); +COMMIT; + +# Transaction that is partially replicated + +START TRANSACTION; +INSERT INTO test1.t1 (f1) VALUES (333); +INSERT INTO test2.t1 (f1) VALUES (99999); +COMMIT; + +# +# Make sure binary logs and gtid_executed strings are equal +# + +--sleep 2 +--connection node_2 +--let $effective_uuid = `SELECT LEFT(@@global.gtid_current_pos, 36)` +--let $gtid_executed_node2 = `SELECT @@global.gtid_current_pos;` + +--replace_result $effective_uuid <effective_uuid> +--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/ +SHOW BINLOG EVENTS IN 'master-bin.000001' FROM 256; + +--connection node_3 + +--disable_query_log +--eval SELECT '$gtid_executed_node2' = @@global.gtid_current_pos AS gtid_executed_equal; +--enable_query_log + +--replace_result $effective_uuid <effective_uuid> +--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/ +SHOW BINLOG EVENTS IN 'master-bin.000001' FROM 256; + +# +# Final consistency checks +# + +--let $diff_servers = 2 3 +--source include/diff_servers.inc + +--connection node_3 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +SELECT COUNT(*) = 2 FROM test1.t1 WHERE f1 IN (1,2); +SELECT COUNT(*) = 3 FROM test1.t1 WHERE f1 IN (111,222,333); +SELECT COUNT(*) = 2 FROM test1.t1 WHERE f2 = 'klm'; + +--error 1049 +USE test2; + +# +# Cleanup +# + +--connection node_1 +DROP SCHEMA test1; +DROP SCHEMA test2; + +--sleep 1 + +--connection node_3 +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +STOP SLAVE; +RESET SLAVE ALL; diff --git a/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db_cc.test b/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db_cc.test new file mode 100644 index 00000000000..1604016f3c3 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_as_slave_gtid_replicate_do_db_cc.test @@ -0,0 +1,176 @@ +# +# Test the case where a Galera slave to async replication goes non-prim while +# a stream of replication events including filtered events is arriving +# + +--source include/have_innodb.inc +--source include/have_log_bin.inc +--source include/big_test.inc + +# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--source include/galera_cluster.inc + +--connection node_1 +SET GLOBAL wsrep_on=OFF; +RESET MASTER; +SET GLOBAL wsrep_on=ON; + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3 +SET global wsrep_on=OFF; +RESET MASTER; +SET global wsrep_on=ON; + +--connection node_2 +SET global wsrep_on=OFF; +RESET MASTER; +SET global wsrep_on=ON; + +--connection node_2 +--disable_query_log +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_1; +--enable_query_log +START SLAVE USER='root'; + +--connection node_1 +CREATE SCHEMA test1; +CREATE SCHEMA test2; +USE test1; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +USE test2; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +INSERT INTO test1.t1 (f1) VALUES (1); +INSERT INTO test2.t1 (f1) VALUES (1); + +INSERT INTO test1.t1 (f1) VALUES (2); +INSERT INTO test2.t1 (f1) VALUES (2); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +--let $wait_condition = SELECT COUNT(*) = 2 FROM test1.t1; +--source include/wait_condition.inc + +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; + +--connection node_1 +INSERT INTO test1.t1 (f1) VALUES (3); +INSERT INTO test2.t1 (f1) VALUES (3); +INSERT INTO test1.t1 (f1) VALUES (3); +INSERT INTO test2.t1 (f1) VALUES (3); +INSERT INTO test1.t1 (f1) VALUES (3); +INSERT INTO test2.t1 (f1) VALUES (3); +INSERT INTO test1.t1 (f1) VALUES (3); +INSERT INTO test2.t1 (f1) VALUES (3); + +--connection node_2 +SET SESSION wsrep_on=OFF; +--let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE variable_name = 'wsrep_cluster_status'; +--source include/wait_condition.inc + +--let $slave_sql_errno = 1047 +--source include/wait_for_slave_sql_error.inc + +--connection node_1 +INSERT INTO test1.t1 (f1) VALUES (4); +INSERT INTO test2.t1 (f1) VALUES (4); +INSERT INTO test1.t1 (f1) VALUES (4); +INSERT INTO test2.t1 (f1) VALUES (4); +INSERT INTO test1.t1 (f1) VALUES (4); +INSERT INTO test2.t1 (f1) VALUES (4); +INSERT INTO test1.t1 (f1) VALUES (4); +INSERT INTO test2.t1 (f1) VALUES (4); +INSERT INTO test1.t1 (f1) VALUES (4); +INSERT INTO test2.t1 (f1) VALUES (4); + +--connection node_2 +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; + +--connection node_1 +INSERT INTO test1.t1 (f1) VALUES (5); +INSERT INTO test2.t1 (f1) VALUES (5); + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE variable_name = 'wsrep_cluster_status'; +--source include/wait_condition.inc +SET SESSION wsrep_on=ON; +--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE variable_name = 'wsrep_ready'; +--source include/wait_condition.inc + +--connection node_1 +INSERT INTO test1.t1 (f1) VALUES (6); +INSERT INTO test2.t1 (f1) VALUES (6); + +--connection node_2 +START SLAVE; + +# +# Consistency checks +# + +--sleep 2 +--connection node_2 +--let $wait_condition = SELECT COUNT(DISTINCT f1) = 6 FROM test1.t1; +--source include/wait_condition.inc + +--connection node_3 +--let $wait_condition = SELECT COUNT(DISTINCT f1) = 6 FROM test1.t1; +--source include/wait_condition.inc + +--connection node_2 +--let $gtid_executed_node2 = `SELECT @@global.gtid_executed;` + +--let $effective_uuid_1 = `SELECT SUBSTRING_INDEX(@@global.gtid_executed, ':', 1)` +--let $effective_uuid_2 = `SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(@@global.gtid_executed, '\n', -1), ':', 1)` + +--replace_result $effective_uuid_1 <effective_uuid_1> $effective_uuid_2 <effective_uuid_2> +--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/ +SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 120; + +--error 1049 +USE test2; + +--connection node_3 + +--disable_query_log +--eval SELECT '$gtid_executed_node2' = @@global.gtid_executed AS gtid_executed_equal; +--enable_query_log + +--error 1049 +USE test2; + +--replace_result $effective_uuid_1 <effective_uuid_1> $effective_uuid_2 <effective_uuid_2> +--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/ +SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 120; + +# +# Cleanup +# + +--connection node_1 +DROP SCHEMA test1; +DROP SCHEMA test2; + +--sleep 1 + +--connection node_3 +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +--connection node_2 +STOP SLAVE; +RESET SLAVE ALL; +CALL mtr.add_suppression("GTID replication failed"); +CALL mtr.add_suppression("Slave SQL: Error in Xid_log_event: Commit could not be completed"); +CALL mtr.add_suppression("Slave SQL: Node has dropped from cluster, Error_code: 1047"); +CALL mtr.add_suppression("TO isolation failed for"); +CALL mtr.add_suppression("Slave SQL: Error 'Deadlock found when trying to get lock; try restarting transaction' on query"); +CALL mtr.add_suppression("Slave SQL: Error 'WSREP has not yet prepared node for application use' on query"); +CALL mtr.add_suppression("Slave: WSREP has not yet prepared node for application use Error_code: 1047"); diff --git a/mysql-test/suite/galera/t/galera_as_slave_nonprim.test b/mysql-test/suite/galera/t/galera_as_slave_nonprim.test index 46a93458271..53b5498a87d 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_nonprim.test +++ b/mysql-test/suite/galera/t/galera_as_slave_nonprim.test @@ -7,22 +7,23 @@ --source include/have_innodb.inc --source include/big_test.inc +--source include/galera_cluster.inc # Step #1. Establish replication # -# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc -# ---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 ---source include/galera_cluster.inc +# As node 4 is not a Galera node, and galera_cluster.inc does not open connetion to it +# we open the node_4 connection here +--connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4 + --connection node_2 --disable_query_log ---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_1, MASTER_USER='root'; +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_4, MASTER_USER='root'; --enable_query_log START SLAVE; SET SESSION wsrep_sync_wait = 0; ---connection node_1 +--connection node_4 CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; --connection node_2 @@ -34,22 +35,21 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; ---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 ---connection node_3 +--connection node_1 --source include/wait_until_connected_again.inc --let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' --source include/wait_condition.inc # Step #3. Force async replication to fail by creating a replication event while the slave is non-prim ---connection node_1 +--connection node_4 INSERT INTO t1 VALUES (1),(2),(3),(4),(5); --connection node_2 --sleep 5 --let $value = query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1) ---connection node_3 +--connection node_1 --disable_query_log --eval SELECT "$value" IN ("Error 'Unknown command' on query. Default database: 'test'. Query: 'BEGIN'", "Node has dropped from cluster") AS expected_error --enable_query_log @@ -58,7 +58,7 @@ INSERT INTO t1 VALUES (1),(2),(3),(4),(5); --connection node_2 SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; ---connection node_3 +--connection node_1 --source include/wait_until_connected_again.inc --let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' --source include/wait_condition.inc @@ -74,7 +74,7 @@ START SLAVE; --let $wait_condition = SELECT COUNT(*) = 5 FROM t1; --source include/wait_condition.inc ---connection node_1 +--connection node_4 DROP TABLE t1; --sleep 2 @@ -92,5 +92,7 @@ CALL mtr.add_suppression("Slave SQL: Error in Xid_log_event: Commit could not be CALL mtr.add_suppression("Slave SQL: Node has dropped from cluster, Error_code: 1047"); ---connection node_1 +--connection node_4 +SET GLOBAL wsrep_on=OFF; RESET MASTER; +SET GLOBAL wsrep_on=ON; diff --git a/mysql-test/suite/galera/t/galera_as_slave_preordered.test b/mysql-test/suite/galera/t/galera_as_slave_preordered.test index 6f221f83b3a..5b3c78b2cb1 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_preordered.test +++ b/mysql-test/suite/galera/t/galera_as_slave_preordered.test @@ -6,14 +6,15 @@ --source include/have_innodb.inc --source include/have_log_bin.inc - -# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc ---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 --source include/galera_cluster.inc +# As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it +# we open the node_3 connection here +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 + --connection node_2 --disable_query_log ---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_1; +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_3; --enable_query_log START SLAVE USER='root'; @@ -21,7 +22,7 @@ START SLAVE USER='root'; # Issue many large-ish transaction on the async master # ---connection node_1 +--connection node_3 CREATE TABLE ten (f1 INTEGER); INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); @@ -63,8 +64,7 @@ while ($count) SELECT COUNT(DISTINCT f1) = 2 * 100 * 10 * 10 FROM t1; ---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 ---connection node_3 +--connection node_1 SELECT COUNT(*) = 2 * 100 * 10 * 10 FROM t1; SELECT COUNT(DISTINCT f1) = 2 * 100 * 10 * 10 FROM t1; @@ -72,7 +72,7 @@ SELECT COUNT(DISTINCT f1) = 2 * 100 * 10 * 10 FROM t1; # Cleanup # ---connection node_1 +--connection node_3 DROP TABLE t1; DROP TABLE ten; @@ -80,5 +80,8 @@ DROP TABLE ten; --let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; --source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'ten'; +--source include/wait_condition.inc + STOP SLAVE; RESET SLAVE ALL; diff --git a/mysql-test/suite/galera/t/galera_as_slave_replication_bundle.test b/mysql-test/suite/galera/t/galera_as_slave_replication_bundle.test index 460e040c010..fa5f3f9c7c6 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_replication_bundle.test +++ b/mysql-test/suite/galera/t/galera_as_slave_replication_bundle.test @@ -5,18 +5,19 @@ # --source include/have_innodb.inc - -# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc ---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 --source include/galera_cluster.inc +# As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it +# we open the node_3 connection here +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 + --connection node_2 --disable_query_log ---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1; +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3; --enable_query_log START SLAVE; ---connection node_1 +--connection node_3 CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(2); @@ -36,7 +37,7 @@ INSERT INTO t1 VALUES(5); SELECT COUNT(*) = 4 FROM t1; # Bundle is now complete, the last INSERT and the DROP are delivered ---connection node_1 +--connection node_3 DROP TABLE t1; --connection node_2 diff --git a/mysql-test/suite/galera/t/galera_autoinc_sst_xtrabackup.cnf b/mysql-test/suite/galera/t/galera_autoinc_sst_xtrabackup.cnf index b4bf5f02171..7e557717744 100644 --- a/mysql-test/suite/galera/t/galera_autoinc_sst_xtrabackup.cnf +++ b/mysql-test/suite/galera/t/galera_autoinc_sst_xtrabackup.cnf @@ -1,7 +1,7 @@ !include ../galera_2nodes.cnf [mysqld] -wsrep_sst_method=xtrabackup-v2 +wsrep_sst_method=mariabackup wsrep_sst_auth="root:" [mysqld.1] diff --git a/mysql-test/suite/galera/t/galera_bf_abort_group_commit.cnf b/mysql-test/suite/galera/t/galera_bf_abort_group_commit.cnf new file mode 100644 index 00000000000..612418c17c0 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_bf_abort_group_commit.cnf @@ -0,0 +1,15 @@ +!include ../galera_2nodes.cnf + +# We set repl.commit_order=1 in order to disable provider commit +# ordering. + +[mysqld.1] +log-bin +log-slave-updates +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;repl.commit_order=1' + +[mysqld.2] + +log-bin +log-slave-updates +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;repl.commit_order=1'
\ No newline at end of file diff --git a/mysql-test/suite/galera/t/galera_bf_abort_group_commit.test b/mysql-test/suite/galera/t/galera_bf_abort_group_commit.test new file mode 100644 index 00000000000..255298565f0 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_bf_abort_group_commit.test @@ -0,0 +1,76 @@ +# +# This test uses galera_sr_bf_abort.inc to probe various BF abort points +# for SR transactions with wsrep provider commit ordering disabled. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# Control connection for manipulating sync points on node 1 +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET SESSION wsrep_sync_wait = 0; + +# SR bf abort on fragment +--let $wsrep_trx_fragment_size = 1 +--echo galera_sr_bf_abort_at_commit = 0 +--let $galera_sr_bf_abort_at_commit = 0 + +--echo after_replicate_sync +--let $galera_sr_bf_abort_sync_point = after_replicate_sync +--source suite/galera/t/galera_sr_bf_abort.inc + +--echo local_monitor_master_enter_sync +--let $galera_sr_bf_abort_sync_point = local_monitor_master_enter_sync +--source suite/galera/t/galera_sr_bf_abort.inc + +--echo apply_monitor_master_enter_sync +--let $galera_sr_bf_abort_sync_point = apply_monitor_master_enter_sync +--source suite/galera/t/galera_sr_bf_abort.inc + +--echo commit_monitor_master_enter_sync +--let $galera_sr_bf_abort_sync_point = commit_monitor_master_enter_sync +--source suite/galera/t/galera_sr_bf_abort.inc + +# SR bf abort on commit fragment +--let $wsrep_trx_fragment_size = 1 +--echo galera_sr_bf_abort_at_commit = 1 +--let $galera_sr_bf_abort_at_commit = 1 + +--echo after_replicate_sync +--let $galera_sr_bf_abort_sync_point = after_replicate_sync +--source suite/galera/t/galera_sr_bf_abort.inc + +--echo local_monitor_master_enter_sync +--let $galera_sr_bf_abort_sync_point = local_monitor_master_enter_sync +--source suite/galera/t/galera_sr_bf_abort.inc + +--echo apply_monitor_master_enter_sync +--let $galera_sr_bf_abort_sync_point = apply_monitor_master_enter_sync +--source suite/galera/t/galera_sr_bf_abort.inc + +--echo commit_monitor_master_enter_sync +--let $galera_sr_bf_abort_sync_point = commit_monitor_master_enter_sync +--source suite/galera/t/galera_sr_bf_abort.inc + +# Normal bf abort on commit +--let $wsrep_trx_fragment_size = 0 +--echo galera_sr_bf_abort_at_commit = 1 +--let $galera_sr_bf_abort_at_commit = 1 + +--echo after_replicate_sync +--let $galera_sr_bf_abort_sync_point = after_replicate_sync +--source suite/galera/t/galera_sr_bf_abort.inc + +--echo local_monitor_master_enter_sync +--let $galera_sr_bf_abort_sync_point = local_monitor_master_enter_sync +--source suite/galera/t/galera_sr_bf_abort.inc + +--echo apply_monitor_master_enter_sync +--let $galera_sr_bf_abort_sync_point = apply_monitor_master_enter_sync +--source suite/galera/t/galera_sr_bf_abort.inc + +--echo commit_monitor_master_enter_sync +--let $galera_sr_bf_abort_sync_point = commit_monitor_master_enter_sync +--source suite/galera/t/galera_sr_bf_abort.inc + +CALL mtr.add_suppression("WSREP: fragment replication failed: 1"); diff --git a/mysql-test/suite/galera/t/galera_bf_abort_shutdown.test b/mysql-test/suite/galera/t/galera_bf_abort_shutdown.test new file mode 100644 index 00000000000..1e5fec5842a --- /dev/null +++ b/mysql-test/suite/galera/t/galera_bf_abort_shutdown.test @@ -0,0 +1,22 @@ +# +# This test verifies that the server can be shut down even if +# some of the wsrep transactions are in QUERY_COMMITTING state. +# In this case the shutdown sequence may do a BF abort for the +# connection. +# + +--source include/have_innodb.inc +--source include/galera_cluster.inc + +CREATE TABLE t1 (f1 INT PRIMARY KEY); + +--connection node_2 +SET DEBUG_SYNC = 'wsrep_before_replication WAIT_FOR continue'; +--send INSERT INTO t1 VALUES (1) + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--source include/restart_mysqld.inc + +--connection node_1 + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_create_table_as_select.test b/mysql-test/suite/galera/t/galera_create_table_as_select.test new file mode 100644 index 00000000000..a6c1f657280 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_create_table_as_select.test @@ -0,0 +1,145 @@ +# +# CREATE TABLE AS SELECT tests +# + +--source include/galera_cluster.inc + +--connection node_1 +SET SESSION default_storage_engine=InnoDB; + +# Left table already exists + +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +--error ER_TABLE_EXISTS_ERROR +CREATE TABLE t1 AS SELECT * FROM t2; +DROP TABLE t1,t2; + +# Right table does not exist +--error ER_NO_SUCH_TABLE +CREATE TABLE t1 AS SELECT * FROM t2; + +# No right table at all +CREATE TABLE t1 AS SELECT 1 FROM DUAL; + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; + +--connection node_1 +DROP TABLE t1; + +# Empty right table +--connection node_1 +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 AS SELECT * FROM t2; + +--connection node_2 +SELECT COUNT(*) = 0 FROM t1; + +--connection node_1 +DROP TABLE t1,t2; + +# Right table is MyISAM + +CREATE TABLE t2 (f1 INTEGER) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1),(2),(3),(4),(5); +CREATE TABLE t1 AS SELECT * FROM t2; +SELECT COUNT(*) = 5 FROM t1; + +--connection node_2 +SELECT COUNT(*) = 5 FROM t1; + +--connection node_1 +DROP TABLE t1,t2; + +# Right side is a subquery + +--connection node_1 +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3),(4),(5); +CREATE TABLE t1 AS SELECT MAX(f1) AS f1 FROM t2; + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; +SELECT f1 = 5 FROM t1; + +--connection node_1 +DROP TABLE t1,t2; + +# Inside a stored procedure + +--connection node_1 +DELIMITER |; +CREATE PROCEDURE sp1 () +BEGIN + CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; + INSERT INTO t2 VALUES (1),(2),(3),(4),(5); + CREATE TABLE t1 AS SELECT * FROM t2; +END| +DELIMITER ;| +CALL sp1(); +SELECT COUNT(*) = 5 FROM t1; + +--connection node_2 +SELECT COUNT(*) = 5 FROM t1; + +--connection node_1 +DROP TABLE t1, t2; +DROP PROCEDURE sp1; + +# Inside a prepared statement + +--connection node_1 +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3),(4),(5); + +PREPARE stmt FROM 'CREATE TABLE t1 AS SELECT * FROM t2'; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; +DROP TABLE t1, t2; + +# +# Multi-master conflict +# + +--connection node_1 + +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3),(4),(5); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +LOCK TABLE t2 WRITE; + +--connection node_1 +--send CREATE TABLE t1 AS SELECT * FROM t2; + +--connection node_2 +SELECT COUNT(*) = 5 FROM t2; +CREATE TABLE t1 AS SELECT * FROM t2; + +--connection node_1a +UNLOCK TABLES; + +--connection node_1 +--error ER_TABLE_EXISTS_ERROR,ER_LOCK_DEADLOCK +--reap + +DROP TABLE t1, t2; + +# +# Temporary table +# + +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3),(4),(5); + +CREATE TEMPORARY TABLE t1 AS SELECT * FROM t2; + +--connection node_2 +--error ER_NO_SUCH_TABLE +SELECT * FROM t1; + +CALL mtr.add_suppression("Slave SQL: Error 'Unknown table 'test.t1'' on query"); + +--connection node_1 +DROP TABLE t1, t2; diff --git a/mysql-test/suite/galera/t/galera_defaults.test b/mysql-test/suite/galera/t/galera_defaults.test index facc5180f2f..ffa88ea0a01 100644 --- a/mysql-test/suite/galera/t/galera_defaults.test +++ b/mysql-test/suite/galera/t/galera_defaults.test @@ -19,7 +19,7 @@ source ../wsrep/include/check_galera_version.inc; # Global Variables -SELECT COUNT(*) = 43 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%'; +SELECT COUNT(*) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%'; SELECT VARIABLE_NAME, VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES @@ -54,8 +54,10 @@ ORDER BY VARIABLE_NAME; $wsrep_provider_options =~ s/gcs\.recv_q_hard_limit = .*?;/<GCS_RECV_Q_HARD_LIMIT>;/sgio; $wsrep_provider_options =~ s/ist\.recv_addr = .*?;/<IST_RECV_ADDR>;/sgio; $wsrep_provider_options =~ s/evs\.evict = .*?;/<EVS_EVICT>;/sgio; + $wsrep_provider_options =~ s/repl\.proto_max = .*?;/<REPL_PROTO_MAX>;/sgio; $wsrep_provider_options =~ s/signal = .*?;\s*//sgio; $wsrep_provider_options =~ s/dbug = .*?;\s*//sgio; + $wsrep_provider_options =~ s/gcs.recv_q_hard_limit = .*?;\s*/<RECV_Q_HARD_LIMIT>;/sgio; $wsrep_provider_options =~ s/repl.proto_max = .*?;\s*/<REPL_PROTO_MAX>;/sgio; print $wsrep_provider_options."\n"; EOF diff --git a/mysql-test/suite/galera/t/galera_forced_binlog_format.test b/mysql-test/suite/galera/t/galera_forced_binlog_format.test index 364f41529a4..e9d7fa1c3a3 100644 --- a/mysql-test/suite/galera/t/galera_forced_binlog_format.test +++ b/mysql-test/suite/galera/t/galera_forced_binlog_format.test @@ -7,7 +7,10 @@ --source include/galera_cluster.inc --connection node_1 +SEt GLOBAL wsrep_on=OFF; RESET MASTER; +SEt GLOBAL wsrep_on=ON; +FLUSH BINARY LOGS; SET SESSION binlog_format = 'STATEMENT'; @@ -40,6 +43,6 @@ REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost; DROP USER dummy@localhost; DROP DATABASE testdb_9401; ---source include/galera_end.inc +#--source include/galera_end.inc --echo # End of tests diff --git a/mysql-test/suite/galera/t/galera_ftwrl_drain.test b/mysql-test/suite/galera/t/galera_ftwrl_drain.test index 690e890cdea..857a1a34485 100644 --- a/mysql-test/suite/galera/t/galera_ftwrl_drain.test +++ b/mysql-test/suite/galera/t/galera_ftwrl_drain.test @@ -12,7 +12,7 @@ --source include/galera_cluster.inc --source include/have_innodb.inc --source include/have_debug_sync.inc ---source suite/galera/include/galera_have_debug_sync.inc +--source include/galera_have_debug_sync.inc --connection node_1 CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; diff --git a/mysql-test/suite/galera/t/galera_gcache_recover_full_gcache.test b/mysql-test/suite/galera/t/galera_gcache_recover_full_gcache.test index b7fd9cf3aed..aeca4c6a6ec 100644 --- a/mysql-test/suite/galera/t/galera_gcache_recover_full_gcache.test +++ b/mysql-test/suite/galera/t/galera_gcache_recover_full_gcache.test @@ -48,8 +48,8 @@ DROP TABLE t1; CALL mtr.add_suppression("Skipped GCache ring buffer recovery"); # Confirm that IST did not take place ---let $assert_text = IST first seqno 2 not found from cache, falling back to SST ---let $assert_select = IST first seqno 2 not found from cache, falling back to SST +--let $assert_text = IST first seqno [24] not found from cache, falling back to SST +--let $assert_select = IST first seqno [24] not found from cache, falling back to SST --let $assert_count = 1 --let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.1.err --let $assert_only_after = starting as process diff --git a/mysql-test/suite/galera/t/galera_gtid-master.opt b/mysql-test/suite/galera/t/galera_gtid-master.opt index 8a755e98b00..30317469ae7 100644 --- a/mysql-test/suite/galera/t/galera_gtid-master.opt +++ b/mysql-test/suite/galera/t/galera_gtid-master.opt @@ -1 +1 @@ ---log-bin --log-slave-updates +--log-bin --log-slave-updates --loose-new-servers-for-galera_gtid-test diff --git a/mysql-test/suite/galera/t/galera_gtid_slave.test b/mysql-test/suite/galera/t/galera_gtid_slave.test index 19bfd8e17db..a356f1fceca 100644 --- a/mysql-test/suite/galera/t/galera_gtid_slave.test +++ b/mysql-test/suite/galera/t/galera_gtid_slave.test @@ -58,6 +58,16 @@ SELECT @@global.gtid_binlog_state; --connection node_1 DROP TABLE t1,t2; +SET GLOBAL wsrep_on=OFF; +reset master; +SET GLOBAL wsrep_on=ON; +# +# Unfortunately without the sleep below the following statement fails with "query returned no rows", which +# is difficult to understand given that it is an aggregate query. A "query execution was interrupted" +# warning is also reported by MTR, which is also weird. +# + +--sleep 1 --connection node_2 --let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; @@ -70,10 +80,14 @@ DROP TABLE t1,t2; --connection node_2 STOP SLAVE; RESET SLAVE ALL; +SET GLOBAL wsrep_on=OFF; reset master; +SET GLOBAL wsrep_on=ON; --connection node_3 +SET GLOBAL wsrep_on=OFF; reset master; +SET GLOBAL wsrep_on=ON; --connection node_1 reset master; diff --git a/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.test b/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.test index 3fe94ad16b7..1b1c2411bc2 100644 --- a/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.test +++ b/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.test @@ -8,21 +8,21 @@ --source include/big_test.inc --source include/have_innodb.inc -# As node #1 is not a Galera node, we connect to node #2 in order to run include/galera_cluster.inc ---connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 --source include/galera_cluster.inc +# As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it +# we open the node_3 connection here +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 --echo #Connection 2 --connection node_2 --disable_query_log ---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1,master_use_gtid=slave_pos; +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3,master_use_gtid=slave_pos; --enable_query_log START SLAVE; --sleep 1 - ---echo #Connection 1 ---connection node_1 +--echo #Connection 3 +--connection node_3 CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 int unique) ENGINE=InnoDB; INSERT INTO t2 VALUES(1,11); INSERT INTO t2 VALUES(2,22); @@ -30,7 +30,6 @@ INSERT INTO t2 VALUES(3,33); SELECT @@global.gtid_binlog_state; --source include/save_master_gtid.inc - --echo #Connection 2 --connection node_2 --source include/sync_with_master_gtid.inc @@ -40,9 +39,8 @@ INSERT INTO t2 VALUES(4,44); INSERT INTO t2 VALUES(5,55); INSERT INTO t2 VALUES(6,66); SELECT @@global.gtid_binlog_state; - ---echo #Connection 3 ---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--echo #Connection 1 +--connection node_1 --let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME= 't2'; --source include/wait_condition.inc --let $wait_condition = SELECT COUNT(*) = 6 FROM t2; @@ -53,8 +51,8 @@ INSERT INTO t2 VALUES(8,88); SELECT @@global.gtid_binlog_state; #Perform SST ---echo #Connection 1 ---connection node_1 +--echo #Connection 3 +--connection node_3 CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; SET AUTOCOMMIT=OFF; START TRANSACTION; @@ -62,7 +60,6 @@ INSERT INTO t1 VALUES ('node1_committed_before'); INSERT INTO t1 VALUES ('node1_committed_before'); COMMIT; --source include/save_master_gtid.inc - --echo #Connection 2 --connection node_2 --source include/sync_with_master_gtid.inc @@ -71,22 +68,21 @@ START TRANSACTION; INSERT INTO t1 VALUES ('node2_committed_before'); INSERT INTO t1 VALUES ('node2_committed_before'); COMMIT; - ---echo #Connection 3 ---connection node_3 +--echo #Connection 1 +--connection node_1 --let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME= 't1'; --source include/wait_condition.inc --let $wait_condition = SELECT COUNT(*) = 4 FROM t1; --source include/wait_condition.inc ---let $node_1= node_2 ---let $node_2= node_3 +--let $node_1= node_1 +--let $node_2= node_2 --source include/auto_increment_offset_save.inc ---echo Shutting down server ... ---source include/shutdown_mysqld.inc - - --echo #Connection 2 --connection node_2 +--echo Shutting down server ... +--source include/shutdown_mysqld.inc +--echo #Connection 1 +--connection node_1 --let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' --source include/wait_condition.inc SET AUTOCOMMIT=OFF; @@ -94,51 +90,46 @@ START TRANSACTION; INSERT INTO t1 VALUES ('node1_committed_during'); INSERT INTO t1 VALUES ('node1_committed_during'); COMMIT; - ---echo #Connection 3 ---connection node_3 +--echo #Connection 2 +--connection node_2 --echo Starting server ... --source include/start_mysqld.inc + --source include/wait_until_ready.inc --source include/auto_increment_offset_restore.inc SET AUTOCOMMIT=OFF; START TRANSACTION; -INSERT INTO t1 VALUES ('node3_committed_after'); -INSERT INTO t1 VALUES ('node3_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); +INSERT INTO t1 VALUES ('node2_committed_after'); COMMIT; - ---echo #Connection 2 ---connection node_2 +--echo #Connection 1 +--connection node_1 --let $wait_condition = SELECT COUNT(*) = 8 FROM t1; --source include/wait_condition.inc Select * from t1 order by f1; - ---echo #Connection 3 ---connection node_3 +--echo #Connection 2 +--connection node_2 Select * from t1 order by f1; #SST Done --sleep 1 +--echo #Connection 1 +--connection node_1 +SELECT @@global.gtid_binlog_state; --echo #Connection 2 --connection node_2 SELECT @@global.gtid_binlog_state; - --echo #Connection 3 --connection node_3 -SELECT @@global.gtid_binlog_state; - ---echo #Connection 1 ---connection node_1 SET AUTOCOMMIT=ON; #drop table t1; #CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; - --echo #Connection 2 --connection node_2 SET AUTOCOMMIT=ON; ---echo #Connection 3 ---connection node_3 +--echo #Connection 1 +--connection node_1 SET AUTOCOMMIT=ON; # @@ -148,10 +139,9 @@ SET AUTOCOMMIT=ON; STOP slave; --sleep 1 INSERT INTO t1 VALUES ('node2_slave_stoped'); - ---echo #Connection 1 ---connection node_1 -INSERT INTO t1 VALUES ('node1_normal_entry'); +--echo #Connection 3 +--connection node_3 +INSERT INTO t1 VALUES ('node3_normal_entry'); --source include/save_master_gtid.inc #start slave @@ -163,16 +153,14 @@ start slave; INSERT INTO t1 VALUES ('node2_slave_started'); SELECT count(*) from t1; SELECT @@global.gtid_binlog_state; - ---echo #Connection 3 ---connection node_3 +--echo #Connection 1 +--connection node_1 --let $wait_condition = SELECT COUNT(*) = 12 FROM t1; --source include/wait_condition.inc SELECT count(*) from t1; SELECT @@global.gtid_binlog_state; - ---echo #Connection 1 ---connection node_1 +--echo #Connection 3 +--connection node_3 DROP TABLE t2,t1; # Unfortunately without the sleep below the following statement fails with "query returned no rows", which @@ -181,27 +169,26 @@ DROP TABLE t2,t1; # --sleep 3 - --echo #Connection 2 --connection node_2 --let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2'; --source include/wait_condition.inc - ---echo #Connection 3 ---connection node_3 +--echo #Connection 1 +--connection node_1 --let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; --source include/wait_condition.inc - --echo #Connection 2 --connection node_2 STOP SLAVE; RESET SLAVE ALL; +set global wsrep_on=OFF; reset master; - ---echo #Connection 3 ---connection node_3 -reset master; - +set global wsrep_on=ON; --echo #Connection 1 --connection node_1 +set global wsrep_on=OFF; +reset master; +set global wsrep_on=ON; +--echo #Connection 3 +--connection node_3 reset master; diff --git a/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.cnf b/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.cnf index 41a1aab382b..1542376b2b8 100644 --- a/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.cnf +++ b/mysql-test/suite/galera/t/galera_ist_innodb_flush_logs.cnf @@ -1,7 +1,7 @@ !include ../galera_2nodes.cnf [mysqld] -wsrep_sst_method=xtrabackup-v2 +wsrep_sst_method=mariabackup wsrep_sst_auth=root: innodb_flush_log_at_trx_commit=0 diff --git a/mysql-test/suite/galera/t/galera_ist_progress.test b/mysql-test/suite/galera/t/galera_ist_progress.test index 3ba63415c28..dd93161eab8 100644 --- a/mysql-test/suite/galera/t/galera_ist_progress.test +++ b/mysql-test/suite/galera/t/galera_ist_progress.test @@ -58,8 +58,8 @@ SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0'; --let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.2.err --let $assert_only_after = Need state transfer ---let $assert_text = Receiving IST: 11 writesets, seqnos ---let $assert_select = Receiving IST: 11 writesets, seqnos +--let $assert_text = Receiving IST: 1[13] writesets +--let $assert_select = Receiving IST: 1[13] writesets --source include/assert_grep.inc --let $assert_text = Receiving IST\.\.\. 0\.0% \( 0/11 events\) complete 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 633318629a6..5e2343aa3e6 100644 --- a/mysql-test/suite/galera/t/galera_ist_restart_joiner.test +++ b/mysql-test/suite/galera/t/galera_ist_restart_joiner.test @@ -7,7 +7,7 @@ --source include/galera_cluster.inc --source include/have_innodb.inc --source include/have_debug_sync.inc ---source suite/galera/include/galera_have_debug_sync.inc +--source include/galera_have_debug_sync.inc # This could cause out of storage if run /dev/shm --source include/big_test.inc diff --git a/mysql-test/suite/galera/t/galera_ist_xtrabackup-v2.cnf b/mysql-test/suite/galera/t/galera_ist_xtrabackup-v2.cnf index a762b939f69..75dff78149d 100644 --- a/mysql-test/suite/galera/t/galera_ist_xtrabackup-v2.cnf +++ b/mysql-test/suite/galera/t/galera_ist_xtrabackup-v2.cnf @@ -1,7 +1,7 @@ !include ../galera_2nodes.cnf [mysqld] -wsrep_sst_method=xtrabackup-v2 +wsrep_sst_method=mariabackup wsrep_sst_auth=root: [mysqld.1] diff --git a/mysql-test/suite/galera/t/galera_log_bin.test b/mysql-test/suite/galera/t/galera_log_bin.test index 2f0faa761c5..57df53e29b1 100644 --- a/mysql-test/suite/galera/t/galera_log_bin.test +++ b/mysql-test/suite/galera/t/galera_log_bin.test @@ -36,4 +36,6 @@ DROP TABLE t1; DROP TABLE t2; --connection node_1 +SET GLOBAL wsrep_on=OFF; RESET MASTER; +SET GLOBAL wsrep_on=ON; diff --git a/mysql-test/suite/galera/t/galera_migrate.cnf b/mysql-test/suite/galera/t/galera_migrate.cnf index ed48f208e52..2e1e9f161a9 100644 --- a/mysql-test/suite/galera/t/galera_migrate.cnf +++ b/mysql-test/suite/galera/t/galera_migrate.cnf @@ -29,11 +29,13 @@ wsrep_sync_wait = 15 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port +log-slave-updates [mysqld.4] #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port +log-slave-updates [ENV] NODE_MYPORT_1= @mysqld.1.port diff --git a/mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test b/mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test index 08ed3fac67e..d5ae8e11638 100644 --- a/mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test +++ b/mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test @@ -32,8 +32,8 @@ INSERT INTO t2 VALUES (1); --connection node_2a --sleep 1 SET SESSION wsrep_sync_wait=0; -SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%applied write set%'; -SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Waiting for table metadata lock'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%committing%'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%Waiting for table metadata lock%'; SELECT COUNT(*) = 0 FROM t1; SELECT COUNT(*) = 0 FROM t2; diff --git a/mysql-test/suite/galera/t/galera_parallel_simple.test b/mysql-test/suite/galera/t/galera_parallel_simple.test index 2cd840123cf..51bb1355ba4 100644 --- a/mysql-test/suite/galera/t/galera_parallel_simple.test +++ b/mysql-test/suite/galera/t/galera_parallel_simple.test @@ -47,7 +47,7 @@ SET SESSION wsrep_sync_wait = 0; --let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Waiting for table metadata lock%'; --source include/wait_condition.inc ---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'applied write set%'; +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'committing%'; --source include/wait_condition.inc UNLOCK TABLES; diff --git a/mysql-test/suite/galera/t/galera_pc_recovery.test b/mysql-test/suite/galera/t/galera_pc_recovery.test new file mode 100644 index 00000000000..ae8647eae22 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_pc_recovery.test @@ -0,0 +1,93 @@ +# +# Test the pc.recovery=1 option. Killing all nodes simultaneously and +# restarting them should succeed and the cluster should re-form. +# + +--source include/have_innodb.inc +--source include/galera_cluster.inc +--source include/big_test.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +# Instruct MTR to not restart the nodes automatically when they are killed + +--let $NODE_1_PIDFILE = `SELECT @@pid_file` +--connection node_2 +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 +--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 + +--exec $MYSQLD --defaults-group-suffix=.1 --defaults-file=$MYSQLTEST_VARDIR/my.cnf --wsrep-recover --log-error=$MYSQL_TMP_DIR/galera_wsrep_recover.1.log > $MYSQL_TMP_DIR/galera_wsrep_recover.1.log 2>&1 +--exec $MYSQLD --defaults-group-suffix=.2 --defaults-file=$MYSQLTEST_VARDIR/my.cnf --wsrep-recover --log-error=$MYSQL_TMP_DIR/galera_wsrep_recover.2.log > $MYSQL_TMP_DIR/galera_wsrep_recover.2.log 2>&1 + +--perl + use strict; + my $wsrep_start_position1 = `grep 'WSREP: Recovered position:' $ENV{MYSQL_TMP_DIR}/galera_wsrep_recover.1.log | sed 's/.*WSREP\:\ Recovered\ position://' | sed 's/^[ \t]*//'`; + chomp($wsrep_start_position1); + + my $wsrep_start_position2 = `grep 'WSREP: Recovered position:' $ENV{MYSQL_TMP_DIR}/galera_wsrep_recover.2.log | sed 's/.*WSREP\:\ Recovered\ position://' | sed 's/^[ \t]*//'`; + chomp($wsrep_start_position2); + + die if $wsrep_start_position1 eq '' || $wsrep_start_position2 eq ''; + + open(FILE, ">", "$ENV{MYSQL_TMP_DIR}/galera_wsrep_start_position.inc") or die; + print FILE "--let \$galera_wsrep_start_position1 = $wsrep_start_position1\n"; + print FILE "--let \$galera_wsrep_start_position2 = $wsrep_start_position2\n"; + close FILE; +EOF + +--source $MYSQL_TMP_DIR/galera_wsrep_start_position.inc + +if ($galera_wsrep_start_position1 == '') { + --die "Could not obtain wsrep_start_position." +} + +if ($galera_wsrep_start_position2 == '') { + --die "Could not obtain wsrep_start_position." +} + +--remove_file $MYSQL_TMP_DIR/galera_wsrep_start_position.inc + +# 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 + +--sleep 5 +--connection node_1 +--enable_reconnect +--source include/wait_until_connected_again.inc + +# Confirm that the cluster has re-formed and data is present + +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +SELECT COUNT(*) = 1 FROM t1; + +--connection node_2 +--enable_reconnect +--source include/wait_until_connected_again.inc +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +SELECT COUNT(*) = 1 FROM t1; + +DROP TABLE t1; + +--connection node_1 +CALL mtr.add_suppression("points to own listening address, blacklisting"); +CALL mtr.add_suppression("non weight changing install in S_PRIM"); +CALL mtr.add_suppression("No re-merged primary component found"); + +--connection node_2 +CALL mtr.add_suppression("points to own listening address, blacklisting"); +CALL mtr.add_suppression("non weight changing install in S_PRIM"); +CALL mtr.add_suppression("No re-merged primary component found"); diff --git a/mysql-test/suite/galera/t/galera_split_brain.test b/mysql-test/suite/galera/t/galera_split_brain.test index a85a2ad9b8d..91a2cc326a2 100644 --- a/mysql-test/suite/galera/t/galera_split_brain.test +++ b/mysql-test/suite/galera/t/galera_split_brain.test @@ -1,6 +1,8 @@ # -# Confirm that with two nodes, killing one causes the other to stop accepting connections -# The pc.ignore_sb=true wsrep_provider option is tested in the galera_kill_* tests. +# Confirm that with two nodes, killing one causes the other to stop accepting +# connections. +# The pc.ignore_sb=true wsrep_provider option is tested in the galera_kill_* +# tests. # --source include/galera_cluster.inc diff --git a/mysql-test/suite/galera/t/galera_ssl_upgrade.test b/mysql-test/suite/galera/t/galera_ssl_upgrade.test index a424942da30..6dc3bf7a5a3 100644 --- a/mysql-test/suite/galera/t/galera_ssl_upgrade.test +++ b/mysql-test/suite/galera/t/galera_ssl_upgrade.test @@ -46,4 +46,8 @@ SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_N --source include/wait_condition.inc SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +# 5. Make sure node_2 is ready as well +--connection node_2 +--source include/galera_wait_ready.inc + # Upgrade complete. Both nodes now use the new key and certificate diff --git a/mysql-test/suite/galera/t/galera_sst_mysqldump.test b/mysql-test/suite/galera/t/galera_sst_mysqldump.test index 835fac94a68..b72fa687411 100644 --- a/mysql-test/suite/galera/t/galera_sst_mysqldump.test +++ b/mysql-test/suite/galera/t/galera_sst_mysqldump.test @@ -1,6 +1,6 @@ --source include/big_test.inc --source include/galera_cluster.inc - +--source include/have_innodb.inc --source suite/galera/include/galera_sst_set_mysqldump.inc --let $node_1=node_1 @@ -14,7 +14,6 @@ --source suite/galera/include/galera_st_shutdown_slave.inc --source suite/galera/include/galera_st_clean_slave.inc - --source suite/galera/include/galera_st_kill_slave.inc --source suite/galera/include/galera_st_kill_slave_ddl.inc diff --git a/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2-options.cnf b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2-options.cnf index 3abf2549aae..db17e3f81b7 100644 --- a/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2-options.cnf +++ b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2-options.cnf @@ -1,7 +1,7 @@ !include ../galera_2nodes.cnf [mysqld] -wsrep_sst_method=xtrabackup-v2 +wsrep_sst_method=mariabackup wsrep_sst_auth="root:" wsrep_debug=ON diff --git a/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2.cnf b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2.cnf index 0025b259ec5..2aef1376ab6 100644 --- a/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2.cnf +++ b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2.cnf @@ -1,7 +1,7 @@ !include ../galera_2nodes.cnf [mysqld] -wsrep_sst_method=xtrabackup-v2 +wsrep_sst_method=mariabackup wsrep_sst_auth="root:" wsrep_debug=ON diff --git a/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2_encrypt_with_key.cnf b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2_encrypt_with_key.cnf index 63d05104a37..5a989ea8177 100644 --- a/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2_encrypt_with_key.cnf +++ b/mysql-test/suite/galera/t/galera_sst_xtrabackup-v2_encrypt_with_key.cnf @@ -1,7 +1,7 @@ !include ../galera_2nodes.cnf [mysqld] -wsrep_sst_method=xtrabackup-v2 +wsrep_sst_method=mariabackup wsrep_sst_auth="root:" wsrep_debug=ON diff --git a/mysql-test/suite/galera/t/galera_toi_ddl_error.test b/mysql-test/suite/galera/t/galera_toi_ddl_error.test index c586d97bdb5..6ee2a6e9b16 100644 --- a/mysql-test/suite/galera/t/galera_toi_ddl_error.test +++ b/mysql-test/suite/galera/t/galera_toi_ddl_error.test @@ -27,3 +27,8 @@ SHOW CREATE TABLE t1; DROP TABLE t1; DROP TABLE ten; + +CALL mtr.add_suppression("Ignoring error 'Duplicate entry '111110' for key 'PRIMARY'' on query."); + +--connection node_2 +CALL mtr.add_suppression("Ignoring error 'Duplicate entry '111110' for key 'PRIMARY'' on query.");
\ No newline at end of file diff --git a/mysql-test/suite/galera/t/galera_toi_ddl_locking.test b/mysql-test/suite/galera/t/galera_toi_ddl_locking.test index 12c83a1f87a..91bcadc0e5d 100644 --- a/mysql-test/suite/galera/t/galera_toi_ddl_locking.test +++ b/mysql-test/suite/galera/t/galera_toi_ddl_locking.test @@ -11,20 +11,31 @@ CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; ---connection node_1 -SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue'; ---send ALTER TABLE t1 ADD COLUMN f2 INTEGER; - --let $galera_connection_name = node_1a --let $galera_server_number = 1 --source include/galera_connect.inc +SET SESSION wsrep_sync_wait = 0; --let $galera_connection_name = node_1b --let $galera_server_number = 1 --source include/galera_connect.inc +# node_1c tests write to unrelated table trough a transaction +--let $galera_connection_name = node_1c +--let $galera_server_number = 1 +--source include/galera_connect.inc + +--connection node_1 +SET DEBUG_SYNC= 'RESET'; +SET DEBUG_SYNC = 'alter_table_before_open_tables SIGNAL before_open_tables WAIT_FOR continue'; +--send ALTER TABLE t1 ADD COLUMN f2 INTEGER; +--sleep 10 --connection node_1a -SET SESSION wsrep_sync_wait = 0; +SET DEBUG_SYNC= 'now WAIT_FOR before_open_tables'; + +# if we would retry the insert, it would fail for wrong column count +# on second try +SET wsrep_retry_autocommit=0; # Allowed SELECT COUNT(*) = 0 FROM t1; @@ -32,33 +43,49 @@ SELECT COUNT(*) = 0 FROM t1; # Allowed SELECT COUNT(*) = 0 FROM t2; -# Not allowed ---error ER_LOCK_DEADLOCK,ER_ERROR_DURING_COMMIT -INSERT INTO t1 VALUES (1); +# Not allowed, this will hang because of ALTER +--send INSERT INTO t1 VALUES (1); + +--connection node_1c +SET SESSION wsrep_sync_wait = 0; SET AUTOCOMMIT=OFF; START TRANSACTION; # Allowed +SELECT COUNT(*) = 0 FROM t1; + +# Allowed +SELECT COUNT(*) = 0 FROM t2; + +# Allowed (until commit) INSERT INTO t2 VALUES (1); # Hangs --send COMMIT; ---sleep 1 --connection node_1b SET SESSION wsrep_sync_wait = 0; # The Commit issued above is still not done -SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'Commit'; +--sleep 1 SELECT COUNT(*) = 0 FROM t2; + +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'Commit'; + SET DEBUG_SYNC= 'now SIGNAL continue'; --connection node_1a +--error ER_LOCK_DEADLOCK +--reap + +--connection node_1c +# this will succeeed, becaus the query will be replayed --reap --connection node_1 --reap + SELECT COUNT(*) = 0 FROM t1; SELECT COUNT(*) = 1 FROM t2; @@ -66,11 +93,5 @@ SELECT COUNT(*) = 1 FROM t2; SELECT COUNT(*) = 0 FROM t1; SELECT COUNT(*) = 1 FROM t2; ---connection node_1 -SET DEBUG_SYNC= 'RESET'; - ---connection node_1b -SET DEBUG_SYNC= 'RESET'; - DROP TABLE t1; DROP TABLE t2; diff --git a/mysql-test/suite/galera/t/galera_transaction_replay.test b/mysql-test/suite/galera/t/galera_transaction_replay.test index 29870829ba3..655714f26c9 100644 --- a/mysql-test/suite/galera/t/galera_transaction_replay.test +++ b/mysql-test/suite/galera/t/galera_transaction_replay.test @@ -1,12 +1,25 @@ # -# This test tests the operation of transaction replay. If a potentially conflicting remote transaction arrives at -# just the right time during the commit of a local transaction, the local transaction will be aborted and replayed. +# This test tests the operation of transaction replay. If a potentially +# conflicting remote transaction arrives at just the right time during +# the commit of a local transaction, the local transaction will be aborted +# and replayed. +# +# Because the write set with higher sequence number cannot BF abort +# the victim with lower sequence number, the conflicting remote transaction +# must be executed first and must be allowed to proceed up to the apply +# monitor before sending the COMMIT for the transaction to be replayed. # --source include/galera_cluster.inc --source include/have_innodb.inc --source include/have_debug_sync.inc ---source suite/galera/include/galera_have_debug_sync.inc +--source include/galera_have_debug_sync.inc + +###################################################################### +# +# Scenario #1, the victim will have higher seqno and will be replayed +# +###################################################################### --let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'` @@ -21,34 +34,123 @@ START TRANSACTION; UPDATE t1 SET f2 = 'b' WHERE f1 = 1; SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE; -# Block the commit +# Block the applier on node #1 and issue a conflicting update on node #2 --connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 ---let $galera_sync_point = commit_monitor_enter_sync +SET SESSION wsrep_sync_wait=0; +--let $galera_sync_point = apply_monitor_slave_enter_sync +--source include/galera_set_sync_point.inc + +--connection node_2 +UPDATE t1 SET f2 = 'c' WHERE f1 = 2; + +--connection node_1a +--source include/galera_wait_sync_point.inc +--source include/galera_clear_sync_point.inc + +# Block the commit, send the COMMIT and wait until it gets blocked + +--let $galera_sync_point = commit_monitor_master_enter_sync --source include/galera_set_sync_point.inc --connection node_1 ---send COMMIT; +--send COMMIT -# Wait until commit is blocked --connection node_1a -SET SESSION wsrep_sync_wait = 0; + +--let $galera_sync_point = apply_monitor_slave_enter_sync commit_monitor_master_enter_sync +--source include/galera_wait_sync_point.inc +--source include/galera_clear_sync_point.inc + +# Let the conflicting UPDATE proceed and wait until it hits abort_trx_end. +# The victim transaction still sits in commit_monitor_master_sync_point. + +--let $galera_sync_point = abort_trx_end +--source include/galera_set_sync_point.inc +--let $galera_sync_point = apply_monitor_slave_enter_sync +--source include/galera_signal_sync_point.inc +--let $galera_sync_point = abort_trx_end commit_monitor_master_enter_sync --source include/galera_wait_sync_point.inc -# Issue a conflicting update on node #2 +# Let the transactions proceed +--source include/galera_clear_sync_point.inc +--let $galera_sync_point = abort_trx_end +--source include/galera_signal_sync_point.inc +--let $galera_sync_point = commit_monitor_master_enter_sync +--source include/galera_signal_sync_point.inc + +# Commit succeeds +--connection node_1 +--reap + +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b'; +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; + +# wsrep_local_replays has increased by 1 +--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'` +--disable_query_log +--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old = 1 AS wsrep_local_replays; +--enable_query_log + --connection node_2 -UPDATE t1 SET f2 = 'c' WHERE f1 = 2; +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b'; +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; + +DROP TABLE t1; + +######################################################################### +# +# Scenario #2, the victim will have lower seqno and will not be replayed +# +######################################################################### + +--connection node_1 + +--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'` + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)); +INSERT INTO t1 VALUES (1, 'a'); +INSERT INTO t1 VALUES (2, 'a'); + +--connection node_1 +SET AUTOCOMMIT=ON; +START TRANSACTION; + +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE; + +# Block the commit, send the COMMIT and wait until it gets blocked + +--let $galera_sync_point = commit_monitor_master_enter_sync +--source include/galera_set_sync_point.inc + +--connection node_1 +--send COMMIT -# Wait for both transactions to be blocked --connection node_1a ---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Update_rows_log_event::find_row%'; ---source include/wait_condition.inc ---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'init' AND INFO = 'COMMIT'; ---source include/wait_condition.inc +--let $galera_sync_point = commit_monitor_master_enter_sync +--source include/galera_wait_sync_point.inc +--source include/galera_clear_sync_point.inc + + +# Set sync point at the end of BF abort, issue a conflicting update +# and wait for the conflicting update to hit the sync point. +--let $galera_sync_point = abort_trx_end +--source include/galera_set_sync_point.inc + +--connection node_2 +UPDATE t1 SET f2 = 'c' WHERE f1 = 2; -# Unblock the commit --connection node_1a +--let $galera_sync_point = abort_trx_end commit_monitor_master_enter_sync +--source include/galera_wait_sync_point.inc +--source include/galera_clear_sync_point.inc + +# Let the transactions proceed --source include/galera_clear_sync_point.inc +--let $galera_sync_point = abort_trx_end +--source include/galera_signal_sync_point.inc +--let $galera_sync_point = commit_monitor_master_enter_sync --source include/galera_signal_sync_point.inc # Commit succeeds @@ -58,10 +160,10 @@ UPDATE t1 SET f2 = 'c' WHERE f1 = 2; SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b'; SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; -# wsrep_local_replays has increased by 1 +# wsrep_local_replays should have not increased --let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'` --disable_query_log ---eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old = 1 AS wsrep_local_replays; +--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old = 0 AS wsrep_local_replays; --enable_query_log --connection node_2 @@ -70,55 +172,84 @@ SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; DROP TABLE t1; -#echo "# test for PS replaying" +######################################## # # test replaying of prepared statements # +######################################## + --connection node_1 + +--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'` + CREATE TABLE t1 (i int primary key, j int) ENGINE=INNODB; INSERT INTO t1 VALUES (1, 0), (3, 0); SELECT * FROM t1; - +SET AUTOCOMMIT=ON; PREPARE stmt1 FROM "UPDATE t1 SET j = 1 where i > 0"; -# block the commit of PS + +# Block the applier on node #1 and issue a conflicting update on node #2 --connection node_1a ---let $galera_sync_point = commit_monitor_enter_sync +SET SESSION wsrep_sync_wait=0; +--let $galera_sync_point = apply_monitor_slave_enter_sync --source include/galera_set_sync_point.inc ---connection node_1 ---send EXECUTE stmt1; +--connection node_2 +INSERT INTO t1 VALUES(2,2); -# Wait until commit is blocked --connection node_1a -SET SESSION wsrep_sync_wait = 0; --source include/galera_wait_sync_point.inc +--source include/galera_clear_sync_point.inc -# Issue a conflicting update on node_2 ---connection node_2 -#UPDATE t1 SET j=2; -INSERT INTO t1 VALUES(2,2); +# Block the commit, send the EXECUTE stmt1 and wait until it gets blocked +--let $galera_sync_point = commit_monitor_master_enter_sync +--source include/galera_set_sync_point.inc -# Wait until applying begins in node_1 ---connection node_1a ---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Write_rows_log_event::write_row%'; ---source include/wait_condition.inc +--connection node_1 +SET SESSION wsrep_sync_wait=0; +--send EXECUTE stmt1 -# Unblock the PS commit --connection node_1a + +--let $galera_sync_point = apply_monitor_slave_enter_sync commit_monitor_master_enter_sync +--source include/galera_wait_sync_point.inc --source include/galera_clear_sync_point.inc + +# Let the conflicting INSERT proceed and wait until it hits abort_trx_end. +# The victim transaction still sits in commit_monitor_master_sync_point. + +--let $galera_sync_point = abort_trx_end +--source include/galera_set_sync_point.inc +--let $galera_sync_point = apply_monitor_slave_enter_sync +--source include/galera_signal_sync_point.inc +--let $galera_sync_point = abort_trx_end commit_monitor_master_enter_sync +--source include/galera_wait_sync_point.inc + +# Let the transactions proceed +--source include/galera_clear_sync_point.inc +--let $galera_sync_point = abort_trx_end +--source include/galera_signal_sync_point.inc +--let $galera_sync_point = commit_monitor_master_enter_sync --source include/galera_signal_sync_point.inc # Commit succeeds --connection node_1 --reap +SET SESSION wsrep_sync_wait=7; SELECT * FROM t1; --connection node_2 SELECT * FROM t1; --connection node_1 +# wsrep_local_replays has increased by 1 +--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'` +--disable_query_log +--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old = 1 AS wsrep_local_replays; +--enable_query_log + DEALLOCATE PREPARE stmt1; DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_var_cluster_address.test b/mysql-test/suite/galera/t/galera_var_cluster_address.test index 6d99d35cdac..113233715c2 100644 --- a/mysql-test/suite/galera/t/galera_var_cluster_address.test +++ b/mysql-test/suite/galera/t/galera_var_cluster_address.test @@ -19,8 +19,8 @@ SET GLOBAL wsrep_cluster_address = 'foo://'; # With wsrep_sync_wait, this returns an error -#--error ER_LOCK_WAIT_TIMEOUT -#SHOW STATUS; +--error ER_LOCK_WAIT_TIMEOUT +SHOW STATUS; SET SESSION wsrep_sync_wait=0; @@ -49,10 +49,9 @@ SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VA --connection node_2 --disable_query_log --eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_node2'; +--source include/galera_wait_ready.inc --enable_query_log ---source include/wait_until_connected_again.inc - --connection node_1 SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; @@ -63,7 +62,7 @@ CALL mtr.add_suppression("Failed to initialize backend using 'foo"); CALL mtr.add_suppression("Failed to open channel 'my_wsrep_cluster' at 'foo"); CALL mtr.add_suppression("gcs connect failed: Socket type not supported"); CALL mtr.add_suppression("wsrep::connect\\(\\) failed: 7"); -CALL mtr.add_suppression("gcs_caused\\(\\) returned -103 \\(Software caused connection abort\\)"); +CALL mtr.add_suppression("gcs_caused\\(\\) returned -[0-9]+ \\(Software caused connection abort\\)"); CALL mtr.add_suppression("failed to open gcomm backend connection: 110: failed to reach primary view: 110"); CALL mtr.add_suppression("Failed to open backend connection: -110 \\(Connection timed out\\)"); CALL mtr.add_suppression("gcs connect failed: Connection timed out"); diff --git a/mysql-test/suite/galera/t/galera_var_dirty_reads.test b/mysql-test/suite/galera/t/galera_var_dirty_reads.test index 1f01c4aac07..dc1698ef497 100644 --- a/mysql-test/suite/galera/t/galera_var_dirty_reads.test +++ b/mysql-test/suite/galera/t/galera_var_dirty_reads.test @@ -11,11 +11,6 @@ --let $node_2=node_2 --source include/auto_increment_offset_save.inc -# Save original auto_increment_offset values. ---let $node_1=node_1 ---let $node_2=node_2 ---source include/auto_increment_offset_save.inc - --connection node_2 --let $wsrep_cluster_address_saved = `SELECT @@global.wsrep_cluster_address` @@ -53,6 +48,7 @@ SET @@session.wsrep_dirty_reads=OFF; --error ER_UNKNOWN_COM_ERROR SELECT i, variable_name, variable_value FROM t1, information_schema.session_variables WHERE variable_name LIKE "wsrep_dirty_reads" AND i = 1; + SELECT 1; USE information_schema; @@ -65,6 +61,7 @@ SELECT COUNT(*) >= 10 FROM performance_schema.events_statements_history; --eval SET @@global.wsrep_cluster_address = '$wsrep_cluster_address_saved' --enable_query_log --source include/wait_until_connected_again.inc +--source include/galera_wait_ready.inc --connection node_1 USE test; @@ -72,8 +69,6 @@ SELECT * FROM t1; # Cleanup DROP TABLE t1; ---source include/auto_increment_offset_restore.inc - --source include/galera_end.inc --echo # End of test diff --git a/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.test b/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.test new file mode 100644 index 00000000000..269e28465d8 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_ignore_apply_errors.test @@ -0,0 +1,235 @@ +# +# Test option wsrep_ignore_apply_errors +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + + +# +# Ignore reconciling DDL errors on node_2 +# + +--connection node_2 +SET GLOBAL wsrep_ignore_apply_errors = 1; + +# Drop table that does not exist +--connection node_1 +SET GLOBAL wsrep_on = OFF; +CREATE TABLE t1 (f1 INTEGER); +SET GLOBAL wsrep_on = ON; +DROP TABLE t1; + +# Drop schema that does not exist +SET GLOBAL wsrep_on = OFF; +CREATE SCHEMA s1; +SET GLOBAL wsrep_on = ON; +DROP SCHEMA s1; + +# Drop index that does not exist using DROP INDEX +CREATE TABLE t1 (f1 INTEGER); +SET GLOBAL wsrep_on = OFF; +CREATE INDEX idx1 ON t1 (f1); +SET GLOBAL wsrep_on = ON; +DROP INDEX idx1 ON t1; +DROP TABLE t1; + +# Drop index that does not exist using ALTER TABLE +CREATE TABLE t1 (f1 INTEGER); +SET GLOBAL wsrep_on = OFF; +CREATE INDEX idx1 ON t1 (f1); +SET GLOBAL wsrep_on = ON; +ALTER TABLE t1 DROP INDEX idx1; +DROP TABLE t1; + +# Drop column that does not exist +CREATE TABLE t1 (f1 INTEGER); +SET GLOBAL wsrep_on = OFF; +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +SET GLOBAL wsrep_on = ON; +ALTER TABLE t1 DROP COLUMN f2; +DROP TABLE t1; + + +# +# Ignore reconciling DML errors on node_2 +# + +--connection node_2 +SET GLOBAL wsrep_ignore_apply_errors = 2; + +# Delete row that does not exist +--connection node_1 +CREATE TABLE t1 (f1 INTEGER); +SET GLOBAL wsrep_on = OFF; +INSERT INTO t1 VALUES (1); +SET GLOBAL wsrep_on = ON; +DELETE FROM t1 WHERE f1 = 1; + +--connection node_1 +SELECT COUNT(*) = 0 FROM t1; +--connection node_2 +SELECT COUNT(*) = 0 FROM t1; + +DROP TABLE t1; + +# Delete row that does not exist in a multi statement transaction +--connection node_1 +CREATE TABLE t1 (f1 INTEGER); +INSERT INTO t1 VALUES (2); +SET GLOBAL wsrep_on = OFF; +INSERT INTO t1 VALUES (1); +SET GLOBAL wsrep_on = ON; +START TRANSACTION; +INSERT INTO t1 VALUES (3); +DELETE FROM t1 WHERE f1 = 1; +DELETE FROM t1 WHERE f1 = 2; +COMMIT; + +--connection node_1 +SELECT COUNT(*) = 1 FROM t1; +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; + +DROP TABLE t1; + +# +# Multi-row delete where only one row does not exist +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 5 FROM t1; +--source include/wait_condition.inc + +SET SESSION wsrep_on = OFF; +DELETE FROM t1 WHERE f1 = 3; +SET SESSION wsrep_on = ON; +--connection node_1 +DELETE FROM t1; + +SELECT COUNT(*) = 0 FROM t1; +--connection node_2 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +SELECT COUNT(*) = 0 FROM t1; +DROP TABLE t1; + +# +# Multi-statement delete where only one row does not exist +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 5 FROM t1; +--source include/wait_condition.inc + +SET SESSION wsrep_on = OFF; +DELETE FROM t1 WHERE f1 = 3; +SET SESSION wsrep_on = ON; +--connection node_1 + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +DELETE FROM t1 WHERE f1 = 1; +DELETE FROM t1 WHERE f1 = 2; +DELETE FROM t1 WHERE f1 = 3; +DELETE FROM t1 WHERE f1 = 4; +DELETE FROM t1 WHERE f1 = 5; +COMMIT; +SET AUTOCOMMIT=ON; + +SELECT COUNT(*) = 0 FROM t1; +--connection node_2 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +SELECT COUNT(*) = 0 FROM t1; +DROP TABLE t1; + +# +# Multi-table delete +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3); +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 3 FROM t2; +--source include/wait_condition.inc + +SET SESSION wsrep_on = OFF; +DELETE FROM t2 WHERE f1 = 2; +DELETE FROM t1 WHERE f1 = 3; +SET SESSION wsrep_on = ON; + +--connection node_1 +DELETE t1, t2 FROM t1 JOIN t2 WHERE t1.f1 = t2.f1; +SELECT COUNT(*) = 0 FROM t1; + +--connection node_2 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +SELECT COUNT(*) = 0 FROM t1; +DROP TABLE t1,t2; + +# +# Foreign keys +# + +--connection node_1 +CREATE TABLE parent (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB; +INSERT INTO parent VALUES (1),(2),(3); +CREATE TABLE child (id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE) ENGINE=INNODB; +INSERT INTO child VALUES (1,1),(2,2),(3,3); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 3 FROM child; +--source include/wait_condition.inc + +SET SESSION wsrep_on = OFF; +DELETE FROM child WHERE parent_id = 2; +SET SESSION wsrep_on = ON; + +--connection node_1 +DELETE FROM parent; +SELECT COUNT(*) = 0 FROM parent; +SELECT COUNT(*) = 0 FROM child; + +--connection node_2 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +SELECT COUNT(*) = 0 FROM parent; +SELECT COUNT(*) = 0 FROM child; +DROP TABLE child, parent; + +# +# Ignore all DDL errors on node_2 +# + +--connection node_2 +SET GLOBAL wsrep_ignore_apply_errors = 4; + +# Create a table that already exists +--connection node_2 +SET GLOBAL wsrep_on = OFF; +CREATE TABLE t1 (f1 INTEGER); +SET GLOBAL wsrep_on = ON; +--connection node_1 +CREATE TABLE t1 (f1 INTEGER, f2 INTEGER); +DROP TABLE t1; + + +--connection node_2 +SET GLOBAL wsrep_ignore_apply_errors = 7; + +CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows event"); + +CALL mtr.add_suppression("Slave SQL: Error 'Unknown table 'test.t1'' on query. Default database: 'test'. Query: 'DROP TABLE t1', Error_code: 1051"); +CALL mtr.add_suppression("Slave SQL: Error 'Can't drop database 's1'; database doesn't exist' on query. Default database: 'test'. Query: 'DROP SCHEMA s1', Error_code: 1008"); +CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'idx1'; check that column/key exists' on query. Default database: 'test'. Query: 'DROP INDEX idx1 ON t1', Error_code: 1091"); +CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'idx1'; check that column/key exists' on query. Default database: 'test'. Query: 'ALTER TABLE t1 DROP INDEX idx1', Error_code: 1091"); +CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'f2'; check that column/key exists' on query. Default database: 'test'. Query: 'ALTER TABLE t1 DROP COLUMN f2', Error_code: 1091"); +CALL mtr.add_suppression("Slave SQL: Error 'Table 't1' already exists' on query."); diff --git a/mysql-test/suite/galera/t/galera_var_log_bin.cnf b/mysql-test/suite/galera/t/galera_var_log_bin.cnf index f7f17e3720a..30ccee2024e 100644 --- a/mysql-test/suite/galera/t/galera_var_log_bin.cnf +++ b/mysql-test/suite/galera/t/galera_var_log_bin.cnf @@ -3,3 +3,8 @@ [mysqld] log-bin +[mysqld.1] +log-slave-updates + +[mysqld.2] +log-slave-updates diff --git a/mysql-test/suite/galera/t/galera_var_slave_threads.test b/mysql-test/suite/galera/t/galera_var_slave_threads.test index e5986f7ee12..db8a8879415 100644 --- a/mysql-test/suite/galera/t/galera_var_slave_threads.test +++ b/mysql-test/suite/galera/t/galera_var_slave_threads.test @@ -21,7 +21,8 @@ SELECT @@wsrep_slave_threads = 1; SET GLOBAL wsrep_slave_threads = 1; # There is a separate wsrep_aborter thread at all times -SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; +SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; # # Increase the number of slave threads. The change takes effect immediately @@ -33,7 +34,15 @@ SET GLOBAL wsrep_slave_threads = 64; INSERT INTO t1 VALUES (1); --connection node_2 ---let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%'); +SELECT COUNT(*) = 1 FROM t1; + +# +# note, in wsrep API #26, we have 2 rollbacker threads, counted as system user's +# +SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; + +--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%'); --source include/wait_condition.inc # @@ -53,51 +62,113 @@ while ($count) } --connection node_2 -SELECT COUNT(*) FROM t2; +SELECT COUNT(*) = 64 FROM t2; +SET wsrep_sync_wait=0; ---let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%') +SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; + +--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%') --source include/wait_condition.inc SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; +--let $wsrep_cluster_address_node2 = `SELECT @@wsrep_cluster_address` +--let $wsrep_provider_node2 = `SELECT @@wsrep_provider` ---eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig +SET GLOBAL wsrep_slave_threads = 5; +--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon' +--source include/wait_condition.inc -DROP TABLE t1; -DROP TABLE t2; +SET GLOBAL wsrep_slave_threads = 1; ---echo # ---echo # lp:1372840 - Changing wsrep_slave_threads causes future connections to hang ---echo # +# +# test phase for bug https://github.com/codership/mysql-wsrep/issues/319 +# +# shutdown node 2 +--connection node_2 +--echo Shutting down server ... +--source include/shutdown_mysqld.inc + +# wait until node_1 is ready as one node cluster --connection node_1 -CREATE TABLE t1 (i INT AUTO_INCREMENT PRIMARY KEY) ENGINE=INNODB; +SET wsrep_sync_wait=0; +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +show status like 'wsrep_cluster_size'; ---connection node_2 -SET GLOBAL wsrep_slave_threads = 4; ---let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%') +# step up slave threads to 6, and make sure all appliers and rollbacker thread are running +SET GLOBAL wsrep_slave_threads = 6; +--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon' --source include/wait_condition.inc +# change to invalid cluster address SET GLOBAL wsrep_slave_threads = 1; +SET GLOBAL wsrep_cluster_address=''; ---connection node_1 -INSERT INTO t1 VALUES (DEFAULT); -INSERT INTO t1 VALUES (DEFAULT); -INSERT INTO t1 VALUES (DEFAULT); -DROP TABLE t1; +# join back to single node cluster +SET GLOBAL wsrep_cluster_address='gcomm://'; +--source include/wait_until_connected_again.inc ---connection node_2 +# we should have 1 applier thread now +--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon' +--source include/wait_condition.inc -# Wait until above DDL is replicated ---let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t%'; +# test if we can increase applier count now (fails in bug #319) +SET GLOBAL wsrep_slave_threads = 10; +--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon' --source include/wait_condition.inc -SELECT NAME FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/t%'; +# restart node 2 +--connection node_2 +--source include/start_mysqld.inc +--source include/wait_until_connected_again.inc + +SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon'; +# # -# make sure that we are left with exactly one applier thread before we leaving the test +# cleanup to original state # ---let $wait_condition = SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%') +--connection node_1 +--eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig + +--connection node_2 +--eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig + +# Generate 64 replication events, to help node 1 to purge excessive applier threads +--let $count = 64 +while ($count) +{ + INSERT INTO t2 VALUES (DEFAULT); + --dec $count +} + +--connection node_1 +# Generate 64 replication events, to help node 2 to purge excessive applier threads +--let $count = 64 +while ($count) +{ + INSERT INTO t2 VALUES (DEFAULT); + --dec $count +} + +--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon' --source include/wait_condition.inc -SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; + + +--connection node_2 +SET GLOBAL wsrep_slave_threads = 4; +--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%') +--source include/wait_condition.inc + +SET GLOBAL wsrep_slave_threads = 1; + +--connection node_1 +--let $wait_condition = SELECT COUNT(*) = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon' +--source include/wait_condition.inc + +DROP TABLE t1; +DROP TABLE t2; --echo # End of tests diff --git a/mysql-test/suite/galera/t/galera_vote_drop_temporary-master.opt b/mysql-test/suite/galera/t/galera_vote_drop_temporary-master.opt new file mode 100644 index 00000000000..beae84b3862 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_vote_drop_temporary-master.opt @@ -0,0 +1 @@ +--log-bin diff --git a/mysql-test/suite/galera/t/galera_wsrep_new_cluster.test b/mysql-test/suite/galera/t/galera_wsrep_new_cluster.test index 6ba8ce786c8..28025363019 100644 --- a/mysql-test/suite/galera/t/galera_wsrep_new_cluster.test +++ b/mysql-test/suite/galera/t/galera_wsrep_new_cluster.test @@ -5,7 +5,6 @@ # --source include/galera_cluster.inc ---source include/have_innodb.inc SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_connected'; diff --git a/mysql-test/suite/galera/t/mysql-wsrep#198-master.opt b/mysql-test/suite/galera/t/mysql-wsrep#198-master.opt new file mode 100644 index 00000000000..beae84b3862 --- /dev/null +++ b/mysql-test/suite/galera/t/mysql-wsrep#198-master.opt @@ -0,0 +1 @@ +--log-bin diff --git a/mysql-test/suite/galera/t/partition.test b/mysql-test/suite/galera/t/partition.test index bb5a02411c3..7fa6b9e800c 100644 --- a/mysql-test/suite/galera/t/partition.test +++ b/mysql-test/suite/galera/t/partition.test @@ -131,9 +131,12 @@ CREATE TABLE t1 (pk INT PRIMARY KEY) --connection node_2 SELECT COUNT(*) = 20002 FROM t1; -# LOAD-ing 20002 rows causes 3 commits to be registered +# LOAD-ing 20002 rows causes +# 3 commits to be registered when the Galera library does not support streaming replication and +# 5 commits to be registered when the Galera library supports streaming replication --disable_query_log ---eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 3 AS wsrep_last_committed_diff; +--replace_result 3 AS_EXPECTED_3_or_5 5 AS_EXPECTED_3_or_5 +--eval SELECT $wsrep_last_committed_after - $wsrep_last_committed_before AS wsrep_last_committed_diff; --enable_query_log DROP TABLE t1; @@ -161,7 +164,7 @@ SELECT COUNT(*) = 101 FROM t1; # LOAD-ing 101 rows causes 1 commit to be registered --disable_query_log ---eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 1 AS wsrep_last_committed_diff; +--eval SELECT $wsrep_last_committed_after - $wsrep_last_committed_before AS wsrep_last_committed_diff; --enable_query_log DROP TABLE t1; @@ -188,9 +191,12 @@ CREATE TABLE t1 (pk INT PRIMARY KEY) --connection node_2 SELECT COUNT(*) = 20002 FROM t1; -# LOAD-ing 20002 rows causes 1 commit to be registered +# LOAD-ing 20002 rows causes +# 1 commit to be registered when the Galera library does not support streaming replication and +# 2 commits to be registered when the Galera library supports streaming replication --disable_query_log ---eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 1 AS wsrep_last_committed_diff; +--replace_result 1 AS_EXPECTED_1_or_2 2 AS_EXPECTED_1_or_2 +--eval SELECT $wsrep_last_committed_after - $wsrep_last_committed_before AS wsrep_last_committed_diff; --enable_query_log DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/rpl_row_annotate.test b/mysql-test/suite/galera/t/rpl_row_annotate.test index b1cfdb36639..b9bae724d7f 100644 --- a/mysql-test/suite/galera/t/rpl_row_annotate.test +++ b/mysql-test/suite/galera/t/rpl_row_annotate.test @@ -3,11 +3,15 @@ --echo # On node_2 --connection node_2 +SET GLOBAL wsrep_on=OFF; RESET MASTER; +SET GLOBAL wsrep_on=ON; --echo # On node_1 --connection node_1 +SET GLOBAL wsrep_on=OFF; RESET MASTER; +SET GLOBAL wsrep_on=ON; CREATE TABLE t1(i INT)ENGINE=INNODB; INSERT INTO t1 VALUES(1); DELETE FROM t1 WHERE i = 1; @@ -38,5 +42,5 @@ let $start_pos= `select @binlog_start_pos`; # Cleanup DROP TABLE t1; ---source include/galera_end.inc +#--source include/galera_end.inc --echo # End of test diff --git a/mysql-test/suite/galera/t/wsrep_trx_fragment_size_non_sr.test b/mysql-test/suite/galera/t/wsrep_trx_fragment_size_non_sr.test new file mode 100644 index 00000000000..f189368cc0f --- /dev/null +++ b/mysql-test/suite/galera/t/wsrep_trx_fragment_size_non_sr.test @@ -0,0 +1,26 @@ +-- source include/galera_cluster.inc + +-- let $sr = `SELECT variable_value LIKE '%:STREAMING:%' FROM information_schema.session_status WHERE variable_name = 'wsrep_provider_capabilities'` + +if ($sr) +{ + -- skip The test requires a wsrep provider that does not support streaming replication. +} + +SELECT variable_value FROM information_schema.session_variables +WHERE variable_name = 'wsrep_trx_fragment_size'; + +SET SESSION wsrep_trx_fragment_size = 0; +-- error ER_WRONG_VALUE_FOR_VAR +SET SESSION wsrep_trx_fragment_size = 123; +SHOW WARNINGS; + +SELECT variable_value FROM information_schema.global_variables +WHERE variable_name = 'wsrep_trx_fragment_size'; + +SET GLOBAL wsrep_trx_fragment_size = 0; +-- error ER_WRONG_VALUE_FOR_VAR +SET GLOBAL wsrep_trx_fragment_size = 123; +SHOW WARNINGS; + +SET GLOBAL wsrep_trx_fragment_size = default; diff --git a/mysql-test/suite/galera/t/wsrep_trx_fragment_size_sr.test b/mysql-test/suite/galera/t/wsrep_trx_fragment_size_sr.test new file mode 100644 index 00000000000..a970cc09afc --- /dev/null +++ b/mysql-test/suite/galera/t/wsrep_trx_fragment_size_sr.test @@ -0,0 +1,22 @@ +-- source include/galera_cluster.inc + +-- let $sr = `SELECT variable_value LIKE '%:STREAMING:%' FROM information_schema.session_status WHERE variable_name = 'wsrep_provider_capabilities'` + +if (!$sr) +{ + -- skip The test requires a wsrep provider that supports streaming replication. +} + +SELECT variable_value FROM information_schema.session_variables +WHERE variable_name = 'wsrep_trx_fragment_size'; + +SET SESSION wsrep_trx_fragment_size = 0; +SET SESSION wsrep_trx_fragment_size = 123; + +SELECT variable_value FROM information_schema.global_variables +WHERE variable_name = 'wsrep_trx_fragment_size'; + +SET GLOBAL wsrep_trx_fragment_size = 0; +SET GLOBAL wsrep_trx_fragment_size = 123; + +SET GLOBAL wsrep_trx_fragment_size = default; diff --git a/mysql-test/suite/galera_3nodes/galera_3nodes.cnf b/mysql-test/suite/galera_3nodes/galera_3nodes.cnf index 91aa53ad7b1..cc6107d62ce 100644 --- a/mysql-test/suite/galera_3nodes/galera_3nodes.cnf +++ b/mysql-test/suite/galera_3nodes/galera_3nodes.cnf @@ -17,6 +17,7 @@ wsrep-sync-wait=15 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port +#wsrep-new-cluster wsrep-cluster-address='gcomm://' wsrep_provider_options='base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S' diff --git a/mysql-test/suite/galera_3nodes/include/galera_suspend.inc b/mysql-test/suite/galera_3nodes/include/galera_suspend.inc index 3495ad2342b..d4037d8958c 100644 --- a/mysql-test/suite/galera_3nodes/include/galera_suspend.inc +++ b/mysql-test/suite/galera_3nodes/include/galera_suspend.inc @@ -9,6 +9,6 @@ my $pid_filename = $ENV{'_SUSPEND_NODE_PIDFILE'}; my $mysqld_pid = `cat $pid_filename`; chomp($mysqld_pid); - system("kill -19 $mysqld_pid"); + system("kill -SIGSTOP $mysqld_pid"); exit(0); EOF diff --git a/mysql-test/suite/galera_3nodes/r/galera_certification_ccc.result b/mysql-test/suite/galera_3nodes/r/galera_certification_ccc.result index b1bbb1406a1..6393a30da6f 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_certification_ccc.result +++ b/mysql-test/suite/galera_3nodes/r/galera_certification_ccc.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; connection node_2; connection node_3; diff --git a/mysql-test/suite/galera_3nodes/r/galera_certification_double_failure.result b/mysql-test/suite/galera_3nodes/r/galera_certification_double_failure.result index c2fdfc38dd5..d43b42bec45 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_certification_double_failure.result +++ b/mysql-test/suite/galera_3nodes/r/galera_certification_double_failure.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; @@ -12,5 +14,6 @@ INSERT INTO t2 VALUES (1); connection node_1; COMMIT; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +connection node_3; DROP TABLE t1; DROP TABLE t2; diff --git a/mysql-test/suite/galera_3nodes/r/galera_ipv6_xtrabackup-v2.result b/mysql-test/suite/galera_3nodes/r/galera_ipv6_xtrabackup-v2.result index 53e35939a79..56348889cf9 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_ipv6_xtrabackup-v2.result +++ b/mysql-test/suite/galera_3nodes/r/galera_ipv6_xtrabackup-v2.result @@ -13,6 +13,3 @@ COUNT(*) = 1 1 DROP TABLE t1; include/assert_grep.inc [Streaming the backup to joiner at \[::1\]] -include/assert_grep.inc [async IST sender starting to serve tcp://\[::1\]:] -include/assert_grep.inc [IST receiver addr using tcp://\[::1\]] -include/assert_grep.inc [Prepared IST receiver, listening at: tcp://\[::1\]] diff --git a/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result b/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result index 3d4dbcc00b0..7780c3f73b8 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result +++ b/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; connection node_2; connection node_3; diff --git a/mysql-test/suite/galera_3nodes/r/galera_pc_bootstrap.result b/mysql-test/suite/galera_3nodes/r/galera_pc_bootstrap.result index 69995acb982..ee49330e892 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_pc_bootstrap.result +++ b/mysql-test/suite/galera_3nodes/r/galera_pc_bootstrap.result @@ -1,8 +1,15 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER); +connection node_1; SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; +connection node_2; SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_3; SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; SET SESSION wsrep_sync_wait = 0; +connection node_2; SET GLOBAL wsrep_provider_options = 'pc.bootstrap=1'; SHOW STATUS LIKE 'wsrep_cluster_size'; Variable_name Value @@ -11,15 +18,21 @@ SHOW STATUS LIKE 'wsrep_cluster_status'; Variable_name Value wsrep_cluster_status Primary INSERT INTO t1 VALUES (1); +connection node_2; SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; +connection node_1; SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; +connection node_3; SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; +connection node_1; SELECT COUNT(*) FROM t1; COUNT(*) 1 +connection node_2; SELECT COUNT(*) FROM t1; COUNT(*) 1 +connection node_3; SELECT COUNT(*) FROM t1; COUNT(*) 1 diff --git a/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result b/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result index 6fb931638ef..a4dca32ff86 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result +++ b/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result @@ -56,9 +56,6 @@ VARIABLE_VALUE = 4 SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; VARIABLE_VALUE = 'Synced' 1 -SET GLOBAL wsrep_provider_options = 'pc.weight=1'; -SET SESSION wsrep_sync_wait=0; -SET SESSION wsrep_sync_wait=0; SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 3 1 @@ -116,6 +113,9 @@ VARIABLE_VALUE = 'Synced' SET GLOBAL wsrep_provider_options = 'pc.weight=1'; CALL mtr.add_suppression('WSREP: gcs_caused\\(\\) returned -1'); CALL mtr.add_suppression('overriding reported weight for'); +CALL mtr.add_suppression('SYNC message from member'); +CALL mtr.add_suppression('user message in state LEAVING'); +CALL mtr.add_suppression('sending install message failed: (Transport endpoint is not connected|Socket is not connected)'); CALL mtr.add_suppression('WSREP: user message in state LEAVING'); -CALL mtr.add_suppression('sending install message failed: Transport endpoint is not connected'); +CALL mtr.add_suppression('sending install message failed: (Transport endpoint is not connected|Socket is not connected)'); CALL mtr.add_suppression('overriding reported weight for'); diff --git a/mysql-test/suite/galera_3nodes/r/galera_wsrep_schema.result b/mysql-test/suite/galera_3nodes/r/galera_wsrep_schema.result new file mode 100644 index 00000000000..89520a7c565 --- /dev/null +++ b/mysql-test/suite/galera_3nodes/r/galera_wsrep_schema.result @@ -0,0 +1,77 @@ +connection node_2; +connection node_1; +SHOW CREATE TABLE wsrep_schema.cluster; +Table Create Table +cluster CREATE TABLE `cluster` ( + `cluster_uuid` char(36) NOT NULL, + `view_id` bigint(20) NOT NULL, + `view_seqno` bigint(20) NOT NULL, + `protocol_version` int(11) NOT NULL, + PRIMARY KEY (`cluster_uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE wsrep_schema.members; +Table Create Table +members CREATE TABLE `members` ( + `node_uuid` char(36) NOT NULL, + `cluster_uuid` char(36) NOT NULL, + `node_name` char(32) NOT NULL, + `node_incoming_address` varchar(256) NOT NULL, + PRIMARY KEY (`node_uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 1 FROM wsrep_schema.cluster; +COUNT(*) = 1 +1 +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster; +cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') +1 +SELECT COUNT(*) = 3 FROM wsrep_schema.members; +COUNT(*) = 3 +1 +SELECT COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') FROM wsrep_schema.members; +COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') +1 +SELECT COUNT(*) = 1 FROM wsrep_schema.members WHERE node_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_gcomm_uuid'); +COUNT(*) = 1 +1 +SELECT node_incoming_address LIKE '127.0.0.1:%' from wsrep_schema.members; +node_incoming_address LIKE '127.0.0.1:%' +1 +1 +1 +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.members; +cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') +1 +1 +1 +SELECT COUNT(*) = 1 FROM wsrep_schema.members WHERE node_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_gcomm_uuid'); +COUNT(*) = 1 +1 +connection node_2; +connection node_1; +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster; +cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') +1 +SELECT COUNT(*) = 2 FROM wsrep_schema.members; +COUNT(*) = 2 +1 +connection node_2; +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster; +cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') +1 +SELECT COUNT(*) = 3 FROM wsrep_schema.members; +COUNT(*) = 3 +1 +connection node_1; +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster; +cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') +1 +SELECT COUNT(*) = 3 FROM wsrep_schema.members; +COUNT(*) = 3 +1 +connection node_1; +CALL mtr.add_suppression("SYNC message from member"); +connection node_2; +CALL mtr.add_suppression("SYNC message from member"); +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_3; +CALL mtr.add_suppression("SYNC message from member"); diff --git a/mysql-test/suite/galera_3nodes/t/GAL-501.test b/mysql-test/suite/galera_3nodes/t/GAL-501.test index 60ed5989227..9e3aff0c437 100644 --- a/mysql-test/suite/galera_3nodes/t/GAL-501.test +++ b/mysql-test/suite/galera_3nodes/t/GAL-501.test @@ -7,6 +7,12 @@ --source include/galera_cluster.inc --source include/have_ipv6.inc +--let $galera_connection_name = node_3 +--let $galera_server_number = 3 +--source include/galera_connect.inc +--connection node_3 +--source include/galera_wait_ready.inc + # Confirm that initial handshake happened over ipv6 SELECT VARIABLE_VALUE LIKE '%[::1]%' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_incoming_addresses'; diff --git a/mysql-test/suite/galera_3nodes/t/galera_certification_double_failure.test b/mysql-test/suite/galera_3nodes/t/galera_certification_double_failure.test index a2ad0765028..5366d2a4a6e 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_certification_double_failure.test +++ b/mysql-test/suite/galera_3nodes/t/galera_certification_double_failure.test @@ -29,5 +29,7 @@ INSERT INTO t2 VALUES (1); --error ER_LOCK_DEADLOCK COMMIT; +--connection node_3 +--source include/galera_wait_ready.inc DROP TABLE t1; DROP TABLE t2; diff --git a/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test b/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test index 03236a3cb93..a4767928681 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test +++ b/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test @@ -60,9 +60,9 @@ DROP TABLE t1; --source include/galera_resume.inc --source include/wait_until_connected_again.inc -CALL mtr.add_suppression("WSREP: gcs_caused() returned -1 \\(Operation not permitted\\)"); - --disable_query_log --eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_node3'; --enable_query_log ---source include/wait_until_connected_again.inc +--source include/galera_wait_ready.inc + +CALL mtr.add_suppression("WSREP: gcs_caused() returned -1 \\(Operation not permitted\\)"); diff --git a/mysql-test/suite/galera_3nodes/t/galera_garbd.test b/mysql-test/suite/galera_3nodes/t/galera_garbd.test index a68ba8ce15b..519f992d1b4 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_garbd.test +++ b/mysql-test/suite/galera_3nodes/t/galera_garbd.test @@ -32,7 +32,10 @@ INSERT INTO t1 VALUES (1); SELECT COUNT(*) = 1 FROM t1; --echo Killing garbd ... ---exec pkill --oldest --full garbd.*$NODE_GALERAPORT_3 +# FreeBSD's /bin/pkill only supports short versions of the options: +# -o Select only the oldest (least recently started) +# -f Match against full argument lists +--exec pkill -o -f garbd.*$NODE_GALERAPORT_3 --sleep 5 diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.cnf b/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.cnf index 8a80be0d2a9..5cc8fb04cdd 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.cnf +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.cnf @@ -5,18 +5,22 @@ wsrep_sst_method=xtrabackup-v2 wsrep_sst_auth="root:" [mysqld.1] +wsrep_node_name='node_1' wsrep-cluster-address=gcomm:// wsrep_provider_options='base_host=[::1];base_port=@mysqld.1.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.1.#galera_port;ist.recv_addr=[::1]:@mysqld.1.#ist_port' wsrep_sst_receive_address='[::1]:@mysqld.1.#sst_port' wsrep_node_incoming_address='[::1]:@mysqld.1.port' [mysqld.2] +wsrep_node_name='node_2' +wsrep_sst_donor='node_1' wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' wsrep_provider_options='base_host=[::1];base_port=@mysqld.2.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.2.#galera_port;ist.recv_addr=[::1]:@mysqld.2.#ist_port' wsrep_sst_receive_address='[::1]:@mysqld.2.#sst_port' wsrep_node_incoming_address='[::1]:@mysqld.2.port' [mysqld.3] +wsrep_node_name='node_3' wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' wsrep_provider_options='base_host=[::1];base_port=@mysqld.3.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.3.#galera_port;ist.recv_addr=[::1]:@mysqld.3.#ist_port' wsrep_sst_receive_address='[::1]:@mysqld.3.#sst_port' diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.test b/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.test index 84eee017700..6756cce6e02 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.test +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.test @@ -42,20 +42,22 @@ DROP TABLE t1; --let $assert_select = Streaming the backup to joiner at \[::1\] --source include/assert_grep.inc ---let $assert_count = 1 ---let $assert_text = async IST sender starting to serve tcp://\[::1\]: ---let $assert_select = async IST sender starting to serve tcp://\[::1\]: ---source include/assert_grep.inc - ---let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.2.err - ---let $assert_text = IST receiver addr using tcp://\[::1\] ---let $assert_select = IST receiver addr using tcp://\[::1\] ---source include/assert_grep.inc - ---let $assert_text = Prepared IST receiver, listening at: tcp://\[::1\] ---let $assert_select = Prepared IST receiver, listening at: tcp://\[::1\] ---source include/assert_grep.inc +# asserts below are not deterministic +# --let $assert_count = 2 +# --let $assert_text = async IST sender starting to serve tcp://\[::1\]: +# --let $assert_select = async IST sender starting to serve tcp://\[::1\]: +# --source include/assert_grep.inc +# +# --let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.2.err +# +# --let $assert_text = IST receiver addr using tcp://\[::1\] +# --let $assert_select = IST receiver addr using tcp://\[::1\] +# --source include/assert_grep.inc +# +# --let $assert_count = 1 +# --let $assert_text = Prepared IST receiver for 4-7, listening at: tcp://\[::1\] +# --let $assert_select = Prepared IST receiver for 4-7, listening at: tcp://\[::1\] +# --source include/assert_grep.inc diff --git a/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test b/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test index a67b30e3fa1..9e43c90bfc1 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test +++ b/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test @@ -11,7 +11,7 @@ --source include/galera_cluster.inc --source include/have_innodb.inc --source include/have_debug_sync.inc ---source suite/galera/include/galera_have_debug_sync.inc +--source include/galera_have_debug_sync.inc --let $galera_connection_name = node_3 --let $galera_server_number = 3 diff --git a/mysql-test/suite/galera_3nodes/t/galera_pc_weight.cnf b/mysql-test/suite/galera_3nodes/t/galera_pc_weight.cnf index 57026ce6928..1a61471d581 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_pc_weight.cnf +++ b/mysql-test/suite/galera_3nodes/t/galera_pc_weight.cnf @@ -1,5 +1,7 @@ -# We need a dedicated .cnf file, even if empty, in order to force this test to run -# alone on a freshly started cluster. Otherwise there are adverse interactions with -# following tests such as galera_3nodes.galera_var_dirty_reads2 +# We need a dedicated .cnf file, even if empty, in order to force this test +# to run alone on a freshly started cluster. Otherwise there are adverse +# interactions with following tests such as +# galera_3nodes.galera_var_dirty_reads2 +!include ../galera_3nodes.cnf !include ../galera_3nodes.cnf diff --git a/mysql-test/suite/galera_3nodes/t/galera_pc_weight.test b/mysql-test/suite/galera_3nodes/t/galera_pc_weight.test index d69881aa5eb..eeb75392f0d 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_pc_weight.test +++ b/mysql-test/suite/galera_3nodes/t/galera_pc_weight.test @@ -1,11 +1,11 @@ # -# Test the pc.weight wsrep provider option. We set Node #1 to have a high weight and then -# suspend it. This will cause Nodes #2 and #3 to transition to non-primary component. +# Test the pc.weight wsrep provider option. We set Node #1 to have a high +# weight and then suspend it. This will cause Nodes #2 and #3 to transition +# to non-primary component. # --source include/big_test.inc --source include/galera_cluster.inc ---source include/have_innodb.inc --connection node_1 SET GLOBAL wsrep_provider_options = 'pc.weight=3'; @@ -49,6 +49,9 @@ SHOW STATUS LIKE 'wsrep_local_state_comment'; --source include/wait_until_connected_again.inc # For Node #1, we expect a primary component of size 1 +# (NOTE: this is a bit racy as nodes 2 and 3 will try to reconnect ASAP. +# to avoid the raice they should be suspended first as well, but that's +# not currently possible) --let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' --source include/wait_condition.inc @@ -59,30 +62,18 @@ SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABL SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state'; SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; -SET GLOBAL wsrep_provider_options = 'pc.weight=1'; - -# Restore the cluster by resetting wsrep_cluster_address on nodes #1 and #2 +# wait for nodes 2 and 3 to reconnect --connection node_2 ---disable_query_log ---eval SET GLOBAL wsrep_cluster_address = @@wsrep_cluster_address; ---enable_query_log - -SET SESSION wsrep_sync_wait=0; ---source include/wait_until_connected_again.inc +--source include/galera_wait_ready.inc --connection node_3 ---disable_query_log ---eval SET GLOBAL wsrep_cluster_address = @@wsrep_cluster_address; ---enable_query_log - -SET SESSION wsrep_sync_wait=0; ---source include/wait_until_connected_again.inc +--source include/galera_wait_ready.inc # On all nodes, we now expect a Primary component of size 3, Synced and ready --connection node_1 ---source include/wait_until_connected_again.inc +--source include/galera_wait_ready.inc SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_connected'; @@ -116,8 +107,11 @@ CALL mtr.add_suppression('WSREP: gcs_caused\\(\\) returned -1'); --connection node_2 CALL mtr.add_suppression('overriding reported weight for'); +CALL mtr.add_suppression('SYNC message from member'); +CALL mtr.add_suppression('user message in state LEAVING'); +CALL mtr.add_suppression('sending install message failed: (Transport endpoint is not connected|Socket is not connected)'); --connection node_3 CALL mtr.add_suppression('WSREP: user message in state LEAVING'); -CALL mtr.add_suppression('sending install message failed: Transport endpoint is not connected'); +CALL mtr.add_suppression('sending install message failed: (Transport endpoint is not connected|Socket is not connected)'); CALL mtr.add_suppression('overriding reported weight for'); diff --git a/mysql-test/suite/galera_3nodes/t/galera_slave_options_ignore.test b/mysql-test/suite/galera_3nodes/t/galera_slave_options_ignore.test index 3e8b1557e7b..8e73dee70ae 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_slave_options_ignore.test +++ b/mysql-test/suite/galera_3nodes/t/galera_slave_options_ignore.test @@ -25,6 +25,7 @@ SELECT COUNT(*) = 1 FROM db2.t2B; --connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 --connection node_3 +--source include/galera_wait_ready.inc SELECT COUNT(*) = 0 FROM db1.t1; SELECT COUNT(*) = 1 FROM db2.t2A; SELECT COUNT(*) = 1 FROM db2.t2B; diff --git a/mysql-test/suite/galera_3nodes/t/galera_wsrep_schema.test b/mysql-test/suite/galera_3nodes/t/galera_wsrep_schema.test new file mode 100644 index 00000000000..9c0b074ab0b --- /dev/null +++ b/mysql-test/suite/galera_3nodes/t/galera_wsrep_schema.test @@ -0,0 +1,74 @@ +# +# This test performs basic checks on the contents of the wsrep_schema +# +# wsrep_schema.members_history checks are temporarily disabled until it +# can be made configurable. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# Make the test fail if table structure has changed + +SHOW CREATE TABLE wsrep_schema.cluster; +SHOW CREATE TABLE wsrep_schema.members; +#disabled SHOW CREATE TABLE wsrep_schema.members_history; + +# Checks for the wsrep_schema.cluster table + +SELECT COUNT(*) = 1 FROM wsrep_schema.cluster; +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster; + +# Checks for the wsrep_schema.members table + +SELECT COUNT(*) = 3 FROM wsrep_schema.members; +SELECT COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') FROM wsrep_schema.members; +SELECT COUNT(*) = 1 FROM wsrep_schema.members WHERE node_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_gcomm_uuid'); + +SELECT node_incoming_address LIKE '127.0.0.1:%' from wsrep_schema.members; +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.members; + +# Checks for the wsrep_schema.members_history table + +#disabled SELECT COUNT(*) = 3 FROM wsrep_schema.members_history; +#disabled SELECT COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') FROM wsrep_schema.members_history; +SELECT COUNT(*) = 1 FROM wsrep_schema.members WHERE node_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_gcomm_uuid'); + +#disabled SELECT last_view_id = (SELECT view_id FROM wsrep_schema.cluster) FROM wsrep_schema.members_history; +#disabled SELECT last_view_seqno = (SELECT view_seqno FROM wsrep_schema.cluster) FROM wsrep_schema.members_history; +#disabled SELECT node_incoming_address LIKE '127.0.0.1:%' from wsrep_schema.members_history; +#disabled SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.members_history; + +--connection node_2 +--source include/shutdown_mysqld.inc + +--connection node_1 +--source include/wait_until_connected_again.inc + +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster; +SELECT COUNT(*) = 2 FROM wsrep_schema.members; +#disabled SELECT COUNT(*) = 3 FROM wsrep_schema.members_history; +#disabled SELECT COUNT(*) = 2 FROM wsrep_schema.members_history WHERE last_view_id = (SELECT MAX(last_view_id) FROM wsrep_schema.members_history); + +--connection node_2 +--source include/start_mysqld.inc +--source include/wait_until_connected_again.inc + +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster; +SELECT COUNT(*) = 3 FROM wsrep_schema.members; +#disabled SELECT COUNT(*) = 3 FROM wsrep_schema.members_history WHERE last_view_id = (SELECT MAX(last_view_id) FROM wsrep_schema.members_history); + +--connection node_1 +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM wsrep_schema.cluster; +SELECT COUNT(*) = 3 FROM wsrep_schema.members; +#disabled SELECT COUNT(*) = 3 FROM wsrep_schema.members_history WHERE last_view_id = (SELECT MAX(last_view_id) FROM wsrep_schema.members_history); + +--connection node_1 +CALL mtr.add_suppression("SYNC message from member"); + +--connection node_2 +CALL mtr.add_suppression("SYNC message from member"); + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3 +CALL mtr.add_suppression("SYNC message from member"); diff --git a/mysql-test/suite/galera_3nodes_ee/galera_3nodes.cnf b/mysql-test/suite/galera_3nodes_ee/galera_3nodes.cnf new file mode 100644 index 00000000000..62c8214b8f2 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/galera_3nodes.cnf @@ -0,0 +1 @@ +!include ../galera_3nodes/galera_3nodes.cnf diff --git a/mysql-test/suite/galera_3nodes_ee/include/galera_check_voting_recovery.inc b/mysql-test/suite/galera_3nodes_ee/include/galera_check_voting_recovery.inc new file mode 100644 index 00000000000..5c74adc46a2 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/include/galera_check_voting_recovery.inc @@ -0,0 +1,58 @@ +# +# Test that after an inconsistency vote that kicked out node #2, the +# cluster is able to recover +# + +# Nodes #1 and #3 remain in the cluster + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; + +--connect node_3X, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3X +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; + +# Node #2 is kicked out + +--connection node_2 +SET SESSION wsrep_on=OFF; +SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +SELECT VARIABLE_VALUE = 'Inconsistent' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +SET SESSION wsrep_on=ON; + +# Restore cluster + +--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +--exec echo "wait" > $_expect_file_name +# Exclude SHOW commands run during server shutdown from sync waiting +--disable_query_log +SET SESSION wsrep_sync_wait = 7; +--enable_query_log +--shutdown_server +--source include/wait_until_disconnected.inc + +--sleep 5 +--source include/start_mysqld.inc +--source include/galera_wait_ready.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_2 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; + +# Confirm that the t1 table is now identical throughout + +--connection node_1 +SHOW CREATE TABLE t1; + +--connection node_2 +SHOW CREATE TABLE t1; + +--connection node_3X +SHOW CREATE TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_ee/my.cnf b/mysql-test/suite/galera_3nodes_ee/my.cnf new file mode 100644 index 00000000000..bb25b95ceea --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/my.cnf @@ -0,0 +1 @@ +!include galera_3nodes.cnf diff --git a/mysql-test/suite/galera_3nodes_ee/r/GCF-354.result b/mysql-test/suite/galera_3nodes_ee/r/GCF-354.result new file mode 100644 index 00000000000..0d52b668e91 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/GCF-354.result @@ -0,0 +1,23 @@ +SET GLOBAL wsrep_on=OFF; +DROP SCHEMA test; +SET GLOBAL wsrep_on=OFF; +CREATE TABLE test.t1 (f1 INTEGER); +CREATE TABLE test.t1 (f1 INTEGER); +SHOW STATUS LIKE 'wsrep_cluster_status'; +Variable_name Value +wsrep_cluster_status Primary +DROP TABLE test.t1; +SET SESSION wsrep_sync_wait=0; +SHOW STATUS LIKE 'wsrep_cluster_status'; +Variable_name Value +wsrep_cluster_status non-Primary +SET SESSION wsrep_sync_wait=0; +SHOW STATUS LIKE 'wsrep_cluster_status'; +Variable_name Value +wsrep_cluster_status non-Primary +CALL mtr.add_suppression("Slave SQL: Error 'Unknown database 'test'' on query. Default database: 'test'. Query: 'CREATE TABLE test.t1 \\\(f1 INTEGER\\\)', Error_code: 1049"); +CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on "); +CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown"); +CALL mtr.add_suppression("Slave SQL: Error 'Table 't1' already exists' on query. Default database: 'test'. Query: 'CREATE TABLE test.t1 \\\(f1 INTEGER\\\)', Error_code: 1050"); +CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on "); +CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown"); diff --git a/mysql-test/suite/galera_3nodes_ee/r/GCF-361.result b/mysql-test/suite/galera_3nodes_ee/r/GCF-361.result new file mode 100644 index 00000000000..6a0af777277 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/GCF-361.result @@ -0,0 +1,16 @@ +SET GLOBAL wsrep_on=OFF; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +FLUSH TABLES WITH READ LOCK; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); +INSERT INTO t1 VALUES(2); +INSERT INTO t1 VALUES(3); +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +UNLOCK TABLES; +DROP TABLE t1; +SET SESSION wsrep_on = OFF; +CALL mtr.add_suppression("Slave SQL: Error 'Table 't1' already exists' on query. Default database: 'test'. Query: 'CREATE TABLE t1 \\\(f1 INTEGER PRIMARY KEY\\\) ENGINE=InnoDB', Error_code: 1050"); +CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on "); +CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown"); diff --git a/mysql-test/suite/galera_3nodes_ee/r/GCF-363.result b/mysql-test/suite/galera_3nodes_ee/r/GCF-363.result new file mode 100644 index 00000000000..ff67cab1303 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/GCF-363.result @@ -0,0 +1,31 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)) ENGINE=InnoDB; +SET GLOBAL wsrep_on=OFF; +INSERT INTO t1 VALUES (1, 'a'); +SET GLOBAL wsrep_on=ON; +SET GLOBAL wsrep_on=OFF; +INSERT INTO t1 VALUES (1, 'a'); +SET GLOBAL wsrep_on=ON; +INSERT INTO t1 VALUES (1, 'b'); +SET SESSION wsrep_sync_wait = 0; +SHOW STATUS LIKE 'wsrep_cluster_status'; +Variable_name Value +wsrep_cluster_status non-Primary +SET SESSION wsrep_on=OFF; +SET SESSION wsrep_on=ON; +SELECT * FROM t1; +f1 f2 +1 a +SELECT * FROM t1; +f1 f2 +1 a +SELECT * FROM t1; +f1 f2 +1 a +DROP TABLE t1; +CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST, end_log_pos 155, Error_code: 1062"); +CALL mtr.add_suppression("WSREP: Event 3 Write_rows apply failed: 121, seqno "); +CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST, end_log_pos 155, Error_code: 1062"); +CALL mtr.add_suppression("WSREP: Event 3 Write_rows apply failed: 121, seqno "); +CALL mtr.add_suppression("WSREP: Vote 0 \\\(success\\\) on (.*) is inconsistent with group. Leaving cluster."); +CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on "); +CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown"); diff --git a/mysql-test/suite/galera_3nodes_ee/r/GCF-376.result b/mysql-test/suite/galera_3nodes_ee/r/GCF-376.result new file mode 100644 index 00000000000..4c699913890 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/GCF-376.result @@ -0,0 +1,48 @@ +CREATE TABLE test.t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)) ENGINE=InnoDB; +SET GLOBAL wsrep_on=OFF; +INSERT INTO t1 VALUES (1, 'a'); +SET GLOBAL wsrep_on=ON; +LOCK TABLE t1 WRITE; +INSERT INTO t1 VALUES (1, 'b'); +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; +SET SESSION wsrep_sync_wait=0; +UNLOCK TABLES; +SHOW STATUS LIKE 'wsrep_cluster_status'; +Variable_name Value +wsrep_cluster_status non-Primary +SET SESSION wsrep_sync_wait=0; +SHOW STATUS LIKE 'wsrep_cluster_status'; +Variable_name Value +wsrep_cluster_status non-Primary +SHOW STATUS LIKE 'wsrep_cluster_size'; +Variable_name Value +wsrep_cluster_size 0 +SET GLOBAL wsrep_on=OFF; +SELECT * FROM t1; +f1 f2 +1 a +SET SESSION wsrep_sync_wait=0; +SHOW STATUS LIKE 'wsrep_cluster_status'; +Variable_name Value +wsrep_cluster_status Primary +SHOW STATUS LIKE 'wsrep_cluster_size'; +Variable_name Value +wsrep_cluster_size 1 +SELECT * FROM t1; +f1 f2 +1 b +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; +SELECT * FROM t1; +f1 f2 +1 b +SELECT * FROM t1; +f1 f2 +1 b +SELECT * FROM t1; +f1 f2 +1 b +DROP TABLE t1; +CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST, end_log_pos (.*), Error_code: 1062"); +CALL mtr.add_suppression("WSREP: Event (.*) Write_rows apply failed: 121, seqno "); +CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on (.*)"); +CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown"); diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera-features#115.result b/mysql-test/suite/galera_3nodes_ee/r/galera-features#115.result new file mode 100644 index 00000000000..a93b73feafc --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/galera-features#115.result @@ -0,0 +1,21 @@ +SET GLOBAL wsrep_on=OFF; +DROP SCHEMA test; +SET GLOBAL wsrep_on=OFF; +CREATE TABLE t1 (f1 INTEGER); +CREATE TABLE t1 (f1 INTEGER); +SET SESSION wsrep_sync_wait=0; +SET SESSION wsrep_sync_wait=0; +SET SESSION wsrep_sync_wait=0; +Killing server ... +Killing server ... +DROP TABLE test.t1; +CALL mtr.add_suppression("Inconsistent by consensus."); +CALL mtr.add_suppression("Error_code: 1049"); +CALL mtr.add_suppression("WSREP: Failed to apply trx: source: "); +CALL mtr.add_suppression("WSREP: Failed to apply app buffer"); +CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster..."); +CALL mtr.add_suppression("Inconsistent by consensus."); +CALL mtr.add_suppression("Error_code: 1050"); +CALL mtr.add_suppression("WSREP: Failed to apply trx: source: "); +CALL mtr.add_suppression("WSREP: Failed to apply app buffer"); +CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster..."); diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera-features#119.result b/mysql-test/suite/galera_3nodes_ee/r/galera-features#119.result new file mode 100644 index 00000000000..5071d6746d1 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/galera-features#119.result @@ -0,0 +1,19 @@ +CREATE TABLE test.t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET GLOBAL wsrep_on=OFF; +INSERT INTO t1 VALUES (1); +LOCK TABLE t1 WRITE; +SET GLOBAL wsrep_sync_wait=0; +INSERT INTO t1 VALUES (1); +SET GLOBAL wsrep_sync_wait=0; +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; +UNLOCK TABLES; +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; +SET GLOBAL wsrep_sync_wait=15; +DROP TABLE test.t1; +Killing server ... +CALL mtr.add_suppression("Inconsistent by consensus."); +CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST"); +CALL mtr.add_suppression("WSREP: Event 3 Write_rows apply failed: 121, seqno"); +CALL mtr.add_suppression("WSREP: Failed to apply trx: source: "); +CALL mtr.add_suppression("WSREP: Failed to apply app buffer: seqno:"); +CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster..."); diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera-features#79.result b/mysql-test/suite/galera_3nodes_ee/r/galera-features#79.result new file mode 100644 index 00000000000..be092572de3 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/galera-features#79.result @@ -0,0 +1,32 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET SESSION wsrep_osu_method=NBO; +SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue'; +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER; +SET SESSION wsrep_sync_wait = 0; +Killing server ... +SET SESSION wsrep_sync_wait = 0; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; +CALL mtr.add_suppression('Failed to send state UUID: -11 \\(Resource temporarily unavailable\\)'); +CALL mtr.add_suppression('discarding established'); +CALL mtr.add_suppression('Quorum: No node with complete state'); +ERROR HY000: Lost connection to MySQL server during query +CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source"); diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_master.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_master.result new file mode 100644 index 00000000000..b8b0f1ca130 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_master.result @@ -0,0 +1,27 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET SESSION wsrep_osu_method=NBO; +SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue'; +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;; +SET SESSION wsrep_sync_wait = 0; +Killing server ... +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; +CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source"); diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_slave_ist.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_slave_ist.result new file mode 100644 index 00000000000..29b87232164 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_slave_ist.result @@ -0,0 +1,35 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET GLOBAL debug = 'd,sync.alter_opened_table'; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;; +SET SESSION wsrep_sync_wait = 0; +Killing server ... +INSERT INTO t1 VALUES (1,2); +INSERT INTO t1 VALUES (2,3); +INSERT INTO t1 VALUES (3,4); +INSERT INTO t1 VALUES (4,5); +INSERT INTO t1 VALUES (5,6); +Performing --wsrep-recover ... +Using --wsrep-start-position when starting mysqld ... +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source"); +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +CALL mtr.add_suppression("WSREP: gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)"); +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_slave_sst.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_slave_sst.result new file mode 100644 index 00000000000..0d687a4d43f --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_kill_slave_sst.result @@ -0,0 +1,33 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET GLOBAL debug = 'd,sync.alter_opened_table'; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;; +SET SESSION wsrep_sync_wait = 0; +Killing server ... +INSERT INTO t1 VALUES (1,2); +INSERT INTO t1 VALUES (2,3); +INSERT INTO t1 VALUES (3,4); +INSERT INTO t1 VALUES (4,5); +INSERT INTO t1 VALUES (5,6); +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source"); +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +CALL mtr.add_suppression("WSREP: gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)"); +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_majority_failure.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_majority_failure.result new file mode 100644 index 00000000000..b9b9fabb1bc --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_majority_failure.result @@ -0,0 +1,46 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_on=OFF; +ALTER TABLE t1 ADD PRIMARY KEY (f1); +SET SESSION wsrep_on=ON; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, DROP PRIMARY KEY; +ERROR 42000: Can't DROP 'PRIMARY'; check that column/key exists +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SET SESSION wsrep_on=OFF; +SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'non-Primary' +1 +SELECT VARIABLE_VALUE = 'Inconsistent' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +VARIABLE_VALUE = 'Inconsistent' +1 +SET SESSION wsrep_on=ON; +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; +CALL mtr.add_suppression("inconsistent with group"); +CALL mtr.add_suppression("Slave SQL: Error"); diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_majority_success.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_majority_success.result new file mode 100644 index 00000000000..e16dfc643d0 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_majority_success.result @@ -0,0 +1,50 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_on=OFF; +ALTER TABLE t1 ADD PRIMARY KEY (f1); +SET SESSION wsrep_on=ON; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1); +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SET SESSION wsrep_on=OFF; +SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'non-Primary' +1 +SELECT VARIABLE_VALUE = 'Inconsistent' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +VARIABLE_VALUE = 'Inconsistent' +1 +SET SESSION wsrep_on=ON; +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t1; +CALL mtr.add_suppression("Slave SQL: Error"); +CALL mtr.add_suppression("Inconsistent by consensus"); +CALL mtr.add_suppression("Failed to execute TOI action"); +CALL mtr.add_suppression("Non-blocking operation end failed"); diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_minority_failure.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_minority_failure.result new file mode 100644 index 00000000000..3efc772cea0 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_minority_failure.result @@ -0,0 +1,52 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_on=OFF; +ALTER TABLE t1 ADD PRIMARY KEY (f1); +SET SESSION wsrep_on=ON; +SET SESSION wsrep_OSU_method='NBO'; +ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1); +ERROR 42000: Multiple primary key defined +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SET SESSION wsrep_on=OFF; +SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'non-Primary' +1 +SELECT VARIABLE_VALUE = 'Inconsistent' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +VARIABLE_VALUE = 'Inconsistent' +1 +SET SESSION wsrep_on=ON; +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CALL mtr.add_suppression("SYNC message from member"); +CALL mtr.add_suppression("Inconsistent by consensus"); +CALL mtr.add_suppression("Failed to execute TOI action"); +CALL mtr.add_suppression("TO isolation end failed"); +CALL mtr.add_suppression("SYNC message from member"); +CALL mtr.add_suppression("SYNC message from member"); diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_minority_success.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_minority_success.result new file mode 100644 index 00000000000..7aa1ac5d8bf --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_minority_success.result @@ -0,0 +1,52 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_on=OFF; +ALTER TABLE t1 ADD PRIMARY KEY (f1); +SET SESSION wsrep_on=ON; +SET SESSION wsrep_on=OFF; +ALTER TABLE t1 ADD PRIMARY KEY (f1); +SET SESSION wsrep_on=ON; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1); +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SET SESSION wsrep_on=OFF; +SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'non-Primary' +1 +SELECT VARIABLE_VALUE = 'Inconsistent' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; +VARIABLE_VALUE = 'Inconsistent' +1 +SET SESSION wsrep_on=ON; +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t1; +CALL mtr.add_suppression("Slave SQL: Error"); +CALL mtr.add_suppression("inconsistent with group"); +CALL mtr.add_suppression("Slave SQL: Error"); diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_non_prim_failure.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_non_prim_failure.result new file mode 100644 index 00000000000..dd4e3674786 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_non_prim_failure.result @@ -0,0 +1,42 @@ +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; +SET SESSION wsrep_osu_method=NBO; +SET SESSION lock_wait_timeout=2; +ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD COLUMN f2 INTEGER;; +SET SESSION wsrep_sync_wait = 0; +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; +SET SESSION wsrep_sync_wait = 0; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; +SET SESSION wsrep_on=OFF; +SET SESSION wsrep_sync_wait = 0; +ERROR HY000: Got error 6 during COMMIT +SET SESSION wsrep_sync_wait = 0; +SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'non-Primary' +1 +INSERT INTO t1 VALUES (2,2); +SET SESSION wsrep_on = OFF; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +DROP TABLE t1; +CALL mtr.add_suppression("Lock wait timeout while waiting NBO end to replicate"); +CALL mtr.add_suppression("Failed to acquire total order isolation for non-blocking DDL end event, provider returned error code 6"); +CALL mtr.add_suppression("This will leave database in inconsistent state since DDL execution cannot be terminated in order"); diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_non_prim_success.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_non_prim_success.result new file mode 100644 index 00000000000..3b7b96d8fde --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_master_non_prim_success.result @@ -0,0 +1,32 @@ +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);; +SET SESSION wsrep_sync_wait = 0; +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; +SET SESSION wsrep_sync_wait = 0; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; +SET SESSION wsrep_on=OFF; +SET SESSION wsrep_sync_wait = 0; +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_shutdown_slave_ist.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_shutdown_slave_ist.result new file mode 100644 index 00000000000..79c7990b158 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_shutdown_slave_ist.result @@ -0,0 +1,28 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET GLOBAL debug = 'd,sync.alter_opened_table'; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;; +SET SESSION wsrep_sync_wait = 0; +INSERT INTO t1 VALUES (1,2); +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source"); +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +CALL mtr.add_suppression("WSREP: gcs_caused() returned -1 \\(Operation not permitted\\)"); +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_slave_non_prim.result b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_slave_non_prim.result new file mode 100644 index 00000000000..4b704facf24 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/galera_nbo_slave_non_prim.result @@ -0,0 +1,35 @@ +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);; +SET SESSION wsrep_sync_wait=0; +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; +SET SESSION wsrep_sync_wait = 0; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 3 FROM wsrep_schema.members; +COUNT(*) = 3 +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; +CALL mtr.add_suppression("gcs_caused\\(\\) returned -1"); diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_toi_vote.result b/mysql-test/suite/galera_3nodes_ee/r/galera_toi_vote.result new file mode 100644 index 00000000000..a0a30f23e25 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/galera_toi_vote.result @@ -0,0 +1,19 @@ +SET GLOBAL wsrep_on=OFF; +DROP SCHEMA test; +CREATE SCHEMA test; +ERROR HY000: Can't create database 'test'; database exists +SET SESSION wsrep_sync_wait=0; +SET SESSION wsrep_sync_wait=0; +SET SESSION wsrep_sync_wait=0; +Killing server ... +CALL mtr.add_suppression("Inconsistent by consensus."); +CALL mtr.add_suppression("Error_code: 1007"); +CALL mtr.add_suppression("WSREP: Failed to apply trx: source: "); +CALL mtr.add_suppression("WSREP: Failed to apply app buffer: seqno: 4, code: "); +CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster..."); +CALL mtr.add_suppression("Inconsistent by consensus."); +CALL mtr.add_suppression("Error_code: 1007"); +CALL mtr.add_suppression("WSREP: Failed to apply trx: source: "); +CALL mtr.add_suppression("WSREP: Failed to apply app buffer: seqno: 4, code: "); +CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster..."); +CALL mtr.add_suppression("inconsistent with group"); diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_vote_rejoin_mysqldump.result b/mysql-test/suite/galera_3nodes_ee/r/galera_vote_rejoin_mysqldump.result new file mode 100644 index 00000000000..64c8b85d440 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/galera_vote_rejoin_mysqldump.result @@ -0,0 +1,60 @@ +Setting SST method to mysqldump ... +GRANT ALL PRIVILEGES ON *.* TO 'sst'; +SET GLOBAL wsrep_sst_auth = 'sst:'; +SET GLOBAL wsrep_sst_method = 'mysqldump'; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_on=OFF; +ALTER TABLE t1 ADD PRIMARY KEY (f1); +SET SESSION wsrep_on=ON; +ALTER TABLE t1 LOCK=SHARED, DROP PRIMARY KEY; +ERROR 42000: Can't DROP 'PRIMARY'; check that column/key exists +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SET SESSION wsrep_on=OFF; +SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'non-Primary' +1 +SET SESSION wsrep_on=ON; +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SET SESSION wsrep_on=OFF; +SET SESSION wsrep_on=ON; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +CALL mtr.add_suppression("is inconsistent with group"); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'PRIMARY'; check that column/key exists'"); +CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query"); +DROP USER sst; +CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query"); +CALL mtr.add_suppression("InnoDB: Error: Table \"mysql\"\\.\"innodb_index_stats\" not found"); +CALL mtr.add_suppression("InnoDB: New log files created"); +CALL mtr.add_suppression("InnoDB: Creating foreign key constraint system tables"); +CALL mtr.add_suppression("Can't open and lock time zone table"); +CALL mtr.add_suppression("Can't open and lock privilege tables"); +CALL mtr.add_suppression("Info table is not ready to be used"); +CALL mtr.add_suppression("Native table .* has the wrong structure"); diff --git a/mysql-test/suite/galera_3nodes_ee/r/galera_vote_sr.result b/mysql-test/suite/galera_3nodes_ee/r/galera_vote_sr.result new file mode 100644 index 00000000000..c2b618b86c4 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/galera_vote_sr.result @@ -0,0 +1,52 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 BLOB) ENGINE=InnoDB; +SET SESSION wsrep_on=OFF; +INSERT INTO t1 VALUES (5, 'X'); +SET SESSION wsrep_on=ON; +DELETE FROM t1 WHERE f1 = 2; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size = 131070; +START TRANSACTION; +INSERT INTO t1 VALUES (1, REPEAT('A', 65535)); +INSERT INTO t1 VALUES (2, REPEAT('A', 65535)); +INSERT INTO t1 VALUES (3, REPEAT('A', 65535)); +INSERT INTO t1 VALUES (4, REPEAT('A', 65535)); +INSERT INTO t1 VALUES (5, REPEAT('A', 65535)); +COMMIT; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +START TRANSACTION; +INSERT INTO t1 VALUES (11, REPEAT('A', 65535)); +INSERT INTO t1 VALUES (12, REPEAT('A', 65535)); +INSERT INTO t1 VALUES (13, REPEAT('A', 65535)); +INSERT INTO t1 VALUES (14, REPEAT('A', 65535)); +INSERT INTO t1 VALUES (15, REPEAT('A', 65535)); +SET SESSION wsrep_on=OFF; +Starting mysqld +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +COMMIT; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 10 FROM t1; +COUNT(*) = 10 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 10 FROM t1; +COUNT(*) = 10 +1 +CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '5' for key 'PRIMARY'"); +CALL mtr.add_suppression("Write_rows apply failed"); +CALL mtr.add_suppression("Inconsistent by consensus"); +CALL mtr.add_suppression("no THD for trx"); +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 10 FROM t1; +COUNT(*) = 10 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_ee/r/mysql-wsrep-features#131.result b/mysql-test/suite/galera_3nodes_ee/r/mysql-wsrep-features#131.result new file mode 100644 index 00000000000..3a6ad0f620f --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/r/mysql-wsrep-features#131.result @@ -0,0 +1,12 @@ +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET SESSION wsrep_osu_method=NBO; +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; +ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);; +SET SESSION wsrep_sync_wait=0; +INSERT INTO t1 VALUES (1);; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-354.cnf b/mysql-test/suite/galera_3nodes_ee/t/GCF-354.cnf new file mode 100644 index 00000000000..e255e1d527e --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-354.cnf @@ -0,0 +1,4 @@ +!include ../galera_3nodes.cnf + +[mysqld] +wsrep-ignore-apply-errors=0 diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-354.test b/mysql-test/suite/galera_3nodes_ee/t/GCF-354.test new file mode 100644 index 00000000000..6dc89594c05 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-354.test @@ -0,0 +1,59 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +# +# 1. Create different inconsistencies on nodes 2 and 3 +# +--connection node_2 +SET GLOBAL wsrep_on=OFF; +DROP SCHEMA test; + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3 +SET GLOBAL wsrep_on=OFF; +CREATE TABLE test.t1 (f1 INTEGER); +# +# 2. The following should generate different errors on nodes 2 and 3 and +# trigger voting with 3 different votes. node_1 should remain alone +# in the cluster. +# +--connection node_1 +CREATE TABLE test.t1 (f1 INTEGER); + +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status' +--source include/wait_condition.inc +SHOW STATUS LIKE 'wsrep_cluster_status'; + +# Test cleanup +DROP TABLE test.t1; +# +# 3. Wait for nodes 2 and 3 to drop out of the cluster and restart them to +# recover the initial configuration. +# +--connection node_2 +SET SESSION wsrep_sync_wait=0; +--let $wait_condition = SELECT VARIABLE_VALUE = 'OFF' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready' +--source include/wait_condition.inc +SHOW STATUS LIKE 'wsrep_cluster_status'; +--source include/restart_mysqld.inc + +--connection node_3 +SET SESSION wsrep_sync_wait=0; +--let $wait_condition = SELECT VARIABLE_VALUE = 'OFF' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready' +--source include/wait_condition.inc +SHOW STATUS LIKE 'wsrep_cluster_status'; +--source include/restart_mysqld.inc +--source include/wait_until_connected_again.inc + +--connection node_2 +--source include/wait_until_connected_again.inc +CALL mtr.add_suppression("Slave SQL: Error 'Unknown database 'test'' on query. Default database: 'test'. Query: 'CREATE TABLE test.t1 \\\(f1 INTEGER\\\)', Error_code: 1049"); +CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on "); +CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown"); + +--connection node_3 +CALL mtr.add_suppression("Slave SQL: Error 'Table 't1' already exists' on query. Default database: 'test'. Query: 'CREATE TABLE test.t1 \\\(f1 INTEGER\\\)', Error_code: 1050"); +CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on "); +CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown"); + diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-361.cnf b/mysql-test/suite/galera_3nodes_ee/t/GCF-361.cnf new file mode 100644 index 00000000000..e255e1d527e --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-361.cnf @@ -0,0 +1,4 @@ +!include ../galera_3nodes.cnf + +[mysqld] +wsrep-ignore-apply-errors=0 diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-361.test b/mysql-test/suite/galera_3nodes_ee/t/GCF-361.test new file mode 100644 index 00000000000..01dbb2147b3 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-361.test @@ -0,0 +1,47 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--let $galera_connection_name = node_3 +--let $galera_server_number = 3 +--source include/galera_connect.inc +--connection node_3 +# create inconsistency +SET GLOBAL wsrep_on=OFF; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +# block the node +FLUSH TABLES WITH READ LOCK; + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); +INSERT INTO t1 VALUES(2); +INSERT INTO t1 VALUES(3); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 3 FROM t1 +--source include/wait_condition.inc +--sleep 1 + +--connection node_3 +SELECT COUNT(*) = 0 FROM t1; +UNLOCK TABLES; +# Wait until the node leaves the cluster +--let $wait_condition = SELECT VARIABLE_VALUE = 'OFF' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready' +--source include/wait_condition.inc + +--connection node_1 +# Wait until node #3 leaves the cluster +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +DROP TABLE t1; + +--connection node_3 +SET SESSION wsrep_on = OFF; +--source include/restart_mysqld.inc +--source include/wait_until_connected_again.inc +--source include/galera_wait_ready.inc + +CALL mtr.add_suppression("Slave SQL: Error 'Table 't1' already exists' on query. Default database: 'test'. Query: 'CREATE TABLE t1 \\\(f1 INTEGER PRIMARY KEY\\\) ENGINE=InnoDB', Error_code: 1050"); +CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on "); +CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown"); diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-363.cnf b/mysql-test/suite/galera_3nodes_ee/t/GCF-363.cnf new file mode 100644 index 00000000000..7b7770e3ad1 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-363.cnf @@ -0,0 +1,8 @@ +!include ../galera_3nodes.cnf + +[mysqld] +wsrep-ignore-apply-errors=0 + +# [mysqld.3] +# wsrep-sst-method=mysqldump +# wsrep_sst_receive_address=127.0.0.2:@mysqld.3.port diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-363.test b/mysql-test/suite/galera_3nodes_ee/t/GCF-363.test new file mode 100644 index 00000000000..0e8e8cc4276 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-363.test @@ -0,0 +1,68 @@ +# +# GCF-363 Inconsistency voting: If in a 3-node cluster the nodes with applier +# error survive, the other node can not join properly +# +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)) ENGINE=InnoDB; + +--connection node_1 +SET GLOBAL wsrep_on=OFF; +INSERT INTO t1 VALUES (1, 'a'); +SET GLOBAL wsrep_on=ON; + +--connection node_2 +SET GLOBAL wsrep_on=OFF; +INSERT INTO t1 VALUES (1, 'a'); +SET GLOBAL wsrep_on=ON; + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3 +INSERT INTO t1 VALUES (1, 'b'); +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT VARIABLE_VALUE = 'OFF' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready' +--source include/wait_condition.inc +SHOW STATUS LIKE 'wsrep_cluster_status'; + +--connection node_1 +# Wait until node #3 leaves the cluster +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +# need to use another connection to restart the node due to GCF-1000 +--connect node_3a, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3a +# ATM (12.11.2016) mysqldump SST does not seem to be working, rsync SST +# requires node restart +# SET GLOBAL wsrep_cluster_address= 'gcomm://127.0.0.1:13001'; +SET SESSION wsrep_on=OFF; +--source include/restart_mysqld.inc +--source include/wait_until_connected_again.inc +SET SESSION wsrep_on=ON; + +--connection node_1 +SELECT * FROM t1; + +--connection node_2 +SELECT * FROM t1; + +--connection node_3a +SELECT * FROM t1; + +DROP TABLE t1; + +--connection node_1 +CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST, end_log_pos 155, Error_code: 1062"); +CALL mtr.add_suppression("WSREP: Event 3 Write_rows apply failed: 121, seqno "); + +--connection node_2 +CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST, end_log_pos 155, Error_code: 1062"); +CALL mtr.add_suppression("WSREP: Event 3 Write_rows apply failed: 121, seqno "); + +--connection node_3a +CALL mtr.add_suppression("WSREP: Vote 0 \\\(success\\\) on (.*) is inconsistent with group. Leaving cluster."); +CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on "); +CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown"); + + diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-376.cnf b/mysql-test/suite/galera_3nodes_ee/t/GCF-376.cnf new file mode 100644 index 00000000000..e255e1d527e --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-376.cnf @@ -0,0 +1,4 @@ +!include ../galera_3nodes.cnf + +[mysqld] +wsrep-ignore-apply-errors=0 diff --git a/mysql-test/suite/galera_3nodes_ee/t/GCF-376.test b/mysql-test/suite/galera_3nodes_ee/t/GCF-376.test new file mode 100644 index 00000000000..b4146a12ebd --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/GCF-376.test @@ -0,0 +1,84 @@ +# +# GCF-376: slaves become inconsistent if master goes non-prim during +# inconsistency voting +# +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE test.t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)) ENGINE=InnoDB; + +--connection node_2 +SET GLOBAL wsrep_on=OFF; +INSERT INTO t1 VALUES (1, 'a'); +SET GLOBAL wsrep_on=ON; + +LOCK TABLE t1 WRITE; + +--connection node_1 +INSERT INTO t1 VALUES (1, 'b'); + +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; +SET SESSION wsrep_sync_wait=0; + +# --sleep 10 +# Wait until node #1 leaves the cluster +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +--connection node_2 +UNLOCK TABLES; + +# Wait until node #2 leaves the cluster +--source include/wsrep_wait_disconnect.inc + +--connection node_1 +SHOW STATUS LIKE 'wsrep_cluster_status'; + +--connection node_2 +SET SESSION wsrep_sync_wait=0; +SHOW STATUS LIKE 'wsrep_cluster_status'; +SHOW STATUS LIKE 'wsrep_cluster_size'; +SET GLOBAL wsrep_on=OFF; +SELECT * FROM t1; + +--connection node_3 +SET SESSION wsrep_sync_wait=0; +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +SHOW STATUS LIKE 'wsrep_cluster_status'; +SHOW STATUS LIKE 'wsrep_cluster_size'; +SELECT * FROM t1; + +# reconnect node #1 +--connection node_1 +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; + +# reconnect node #2 +--connection node_2 +--source include/restart_mysqld.inc +--source include/wait_until_connected_again.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +SELECT * FROM t1; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +SELECT * FROM t1; + +--connection node_3 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +SELECT * FROM t1; + +DROP TABLE t1; + +--connection node_2 +CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST, end_log_pos (.*), Error_code: 1062"); +CALL mtr.add_suppression("WSREP: Event (.*) Write_rows apply failed: 121, seqno "); +CALL mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on (.*)"); +CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown"); diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera-features#115.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera-features#115.cnf new file mode 100644 index 00000000000..e255e1d527e --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera-features#115.cnf @@ -0,0 +1,4 @@ +!include ../galera_3nodes.cnf + +[mysqld] +wsrep-ignore-apply-errors=0 diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera-features#115.test b/mysql-test/suite/galera_3nodes_ee/t/galera-features#115.test new file mode 100644 index 00000000000..fae92aab4e8 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera-features#115.test @@ -0,0 +1,67 @@ +# +# This test tests that one successful node wins over two nodes that fail for +# different reasons +# +--source include/galera_3nodes.inc +--source include/have_innodb.inc + +# create inconsistency on node 2 +--connection node_2 +SET GLOBAL wsrep_on=OFF; +DROP SCHEMA test; + +# create inconsistency on node 3 +--connection node_3 +SET GLOBAL wsrep_on=OFF; +CREATE TABLE t1 (f1 INTEGER); + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER); + +--connection node_1 +SET SESSION wsrep_sync_wait=0; +# wait for nodes 2 and 3 drop from the cluster +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +--source include/wait_condition.inc + +--connection node_2 +SET SESSION wsrep_sync_wait=0; +--let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +--source include/wait_condition.inc + +--connection node_3 +SET SESSION wsrep_sync_wait=0; +--let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +--source include/wait_condition.inc + +# reconnect nodes 2 and 3, since they failed +--connection node_2 +--source include/kill_galera.inc +--sleep 1 +--source include/start_mysqld.inc + +--connection node_3 +--source include/kill_galera.inc +--sleep 1 +--source include/start_mysqld.inc + +--connection node_1 +DROP TABLE test.t1; + +--connection node_2 +CALL mtr.add_suppression("Inconsistent by consensus."); +CALL mtr.add_suppression("Error_code: 1049"); +CALL mtr.add_suppression("WSREP: Failed to apply trx: source: "); +CALL mtr.add_suppression("WSREP: Failed to apply app buffer"); +CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster..."); + +--connection node_3 +CALL mtr.add_suppression("Inconsistent by consensus."); +CALL mtr.add_suppression("Error_code: 1050"); +CALL mtr.add_suppression("WSREP: Failed to apply trx: source: "); +CALL mtr.add_suppression("WSREP: Failed to apply app buffer"); +CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster..."); + + diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera-features#119.test b/mysql-test/suite/galera_3nodes_ee/t/galera-features#119.test new file mode 100644 index 00000000000..e600db4453b --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera-features#119.test @@ -0,0 +1,61 @@ +# +# This test tests voting (successful slave wins) in the absence of the master +# for trasaction. +# +--source include/galera_3nodes.inc +--source include/have_innodb.inc + +CREATE TABLE test.t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +--connection node_2 +--let $wsrep_provider_orig = `SELECT @@wsrep_provider` +--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address` +SET GLOBAL wsrep_on=OFF; +INSERT INTO t1 VALUES (1); +LOCK TABLE t1 WRITE; +SET GLOBAL wsrep_sync_wait=0; + +--connection node_1 +INSERT INTO t1 VALUES (1); +SET GLOBAL wsrep_sync_wait=0; +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; + +--connection node_3 +# wait for node_1 to disappear +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_2 +UNLOCK TABLES; +# wait to go non-Primary due to inconsistency voting +#--let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +#--source include/wait_condition.inc +# Somehow the above times out so we use connectin to node 3 + +--connection node_3 +# wait for node_1 to disappear +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_1 +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; +--source include/galera_wait_ready.inc +SET GLOBAL wsrep_sync_wait=15; +DROP TABLE test.t1; + +# reconnect node 2, since it is now inconsistent +--connection node_2 +--source include/kill_galera.inc +--sleep 1 +--source include/start_mysqld.inc +--sleep 1 + +--connection node_2 +CALL mtr.add_suppression("Inconsistent by consensus."); +CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log FIRST"); +CALL mtr.add_suppression("WSREP: Event 3 Write_rows apply failed: 121, seqno"); +CALL mtr.add_suppression("WSREP: Failed to apply trx: source: "); +CALL mtr.add_suppression("WSREP: Failed to apply app buffer: seqno:"); +CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster..."); + + diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera-features#79.test b/mysql-test/suite/galera_3nodes_ee/t/galera-features#79.test new file mode 100644 index 00000000000..4183dfcfaf5 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera-features#79.test @@ -0,0 +1,75 @@ +# NB-DDL: Assertion `header_size_max() + csize <= size' failed in gu::RecordSetOutBase::write_header + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc +--source include/big_test.inc + +--let $galera_connection_name = node_3 +--let $galera_server_number = 3 +--source include/galera_connect.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +--connection node_2 +SET SESSION wsrep_osu_method=NBO; +# Set the ALTER to block on the master +SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue'; +--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER + +--let $galera_connection_name = node_2a +--let $galera_server_number = 2 +--source include/galera_connect.inc +--connection node_2a + +# Wait until the ALTER has blocked on the master +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER' AND STATE = 'debug sync point: alter_table_before_open_tables'; +--source include/wait_condition.inc + +# Restart the master +--source include/kill_galera.inc +--sleep 5 + +# Make sure the ALTER is aborted on node #1 +--connection node_1 +--source include/wait_until_connected_again.inc +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%' +--source include/wait_condition.inc + +--connection node_2a +--source include/start_mysqld.inc +--sleep 5 + +# Confirm that all nodes have the same view of the database +--connection node_1 +--source include/wait_until_connected_again.inc +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 1 FROM t1; + +--let $galera_connection_name = node_2b +--let $galera_server_number = 2 +--source include/galera_connect.inc +--connection node_2b +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 1 FROM t1; + +--connection node_3 +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 1 FROM t1; + +DROP TABLE t1; + +CALL mtr.add_suppression('Failed to send state UUID: -11 \\(Resource temporarily unavailable\\)'); +CALL mtr.add_suppression('discarding established'); +CALL mtr.add_suppression('Quorum: No node with complete state'); + +--connection node_2 +--error 2013 +--reap + +--connection node_2b +CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source"); diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_master.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_master.test new file mode 100644 index 00000000000..688ada7a120 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_master.test @@ -0,0 +1,73 @@ +# +# This test kills the master (node_2 for this query) while the DDL is running there +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc + +--let $galera_connection_name = node_3 +--let $galera_server_number = 3 +--source include/galera_connect.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +--connection node_2 +SET SESSION wsrep_osu_method=NBO; +# Set the ALTER to block on the master +SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue'; +--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER; + +--let $galera_connection_name = node_2a +--let $galera_server_number = 2 +--source include/galera_connect.inc +--connection node_2a + +# Wait until the ALTER has blocked on the master +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER' AND STATE = 'debug sync point: alter_table_before_open_tables'; +--source include/wait_condition.inc + +# Restart the master +--source include/kill_galera.inc +--sleep 5 + +--connection node_1 +--source include/wait_until_connected_again.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%'; +--source include/wait_condition.inc + +--connection node_2a +--source include/start_mysqld.inc +--sleep 5 + +# Confirm that all nodes have the same view of the database +--connection node_1 +--source include/wait_until_connected_again.inc +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 1 FROM t1; + +--let $galera_connection_name = node_2b +--let $galera_server_number = 2 +--source include/galera_connect.inc +--connection node_2b +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 1 FROM t1; + +--connection node_3 +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 1 FROM t1; + +DROP TABLE t1; + +# CALL mtr.add_suppression('Failed to send state UUID: -11 \\(Resource temporarily unavailable\\)'); +# CALL mtr.add_suppression('discarding established'); +# CALL mtr.add_suppression('Quorum: No node with complete state'); + +--connection node_2b +CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source"); diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_ist.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_ist.test new file mode 100644 index 00000000000..8f08f357046 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_ist.test @@ -0,0 +1,73 @@ +# +# This test kills a slave while a DDL is being applied there +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/big_test.inc + +--let $galera_connection_name = node_3 +--let $galera_server_number = 3 +--source include/galera_connect.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +--connection node_3 +# Set so that the applier thread will block in mysql_alter_table() +--let $debug_orig = `SELECT @@debug` +SET GLOBAL debug = 'd,sync.alter_opened_table'; + +--connection node_1 +SET SESSION wsrep_osu_method=NBO; +--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER; + +--connection node_3 +# Wait until the ALTER above has arrived on the slave and has blocked in the applier thread +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER' AND STATE = 'debug sync point: now'; +--source include/wait_condition.inc + +# Kill the slave (node #3) +--source include/kill_galera.inc +--sleep 5 + +# Wait until node #3 is completely out of the cluster +--connection node_2 +--source include/wait_until_connected_again.inc + +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +INSERT INTO t1 VALUES (1,2); +INSERT INTO t1 VALUES (2,3); +INSERT INTO t1 VALUES (3,4); +INSERT INTO t1 VALUES (4,5); +INSERT INTO t1 VALUES (5,6); + +# Restart node #3 +--connection node_3 +--let $galera_wsrep_recover_server_id=3 +--source suite/galera/include/galera_wsrep_recover.inc + +--source include/start_mysqld.inc +--sleep 10 + +# Check that all nodes have the same view of the database +--source include/wait_until_connected_again.inc +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 5 FROM t1; +CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source"); + +--connection node_2 +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 5 FROM t1; +CALL mtr.add_suppression("WSREP: gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)"); + +--connection node_1 +--reap +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 5 FROM t1; + +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_sst.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_sst.cnf new file mode 100644 index 00000000000..36b1fa112a1 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_sst.cnf @@ -0,0 +1,11 @@ +!include ../galera_3nodes.cnf + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1' + +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=1' + +[mysqld.3] +wsrep_provider_options='base_port=@mysqld.3.#galera_port;gcache.size=1' + diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_sst.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_sst.test new file mode 100644 index 00000000000..9caf2e7299e --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_kill_slave_sst.test @@ -0,0 +1,70 @@ +# +# This test kills a slave while a DDL is being applied there +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/big_test.inc + +--let $galera_connection_name = node_3 +--let $galera_server_number = 3 +--source include/galera_connect.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +--connection node_3 +# Set so that the applier thread will block in mysql_alter_table() +--let $debug_orig = `SELECT @@debug` +SET GLOBAL debug = 'd,sync.alter_opened_table'; + +--connection node_1 +SET SESSION wsrep_osu_method=NBO; +--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER; + +--connection node_3 +# Wait until the ALTER above has arrived on the slave and has blocked in the applier thread +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER' AND STATE = 'debug sync point: now'; +--source include/wait_condition.inc + +# Kill the slave (node #3) +--source include/kill_galera.inc +--sleep 5 + +# Wait until node #3 is completely out of the cluster +--connection node_2 +--source include/wait_until_connected_again.inc + +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +INSERT INTO t1 VALUES (1,2); +INSERT INTO t1 VALUES (2,3); +INSERT INTO t1 VALUES (3,4); +INSERT INTO t1 VALUES (4,5); +INSERT INTO t1 VALUES (5,6); + +# Restart node #3 +--connection node_3 +--source include/start_mysqld.inc +--sleep 10 + +# Check that all nodes have the same view of the database +--source include/wait_until_connected_again.inc +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 5 FROM t1; +CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source"); + +--connection node_2 +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 5 FROM t1; +CALL mtr.add_suppression("WSREP: gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)"); + +--connection node_1 +--reap +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 5 FROM t1; + +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_failure.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_failure.cnf new file mode 100644 index 00000000000..e255e1d527e --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_failure.cnf @@ -0,0 +1,4 @@ +!include ../galera_3nodes.cnf + +[mysqld] +wsrep-ignore-apply-errors=0 diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_failure.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_failure.test new file mode 100644 index 00000000000..f7ff2e379a3 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_failure.test @@ -0,0 +1,38 @@ +# +# Test the situation where the master is in the majority when an NBO DDL fails on master +# + +--source include/galera_cluster.inc +--source include/big_test.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +# Introduce inconsistency on node #2 + +--connection node_2 +--let $wsrep_cluster_address_node2 = `SELECT @@wsrep_cluster_address` +SET SESSION wsrep_on=OFF; +ALTER TABLE t1 ADD PRIMARY KEY (f1); +SET SESSION wsrep_on=ON; + +# Run DDL that will fail on nodes #1 and #3 but succeed on node #2 + +--connection node_1 +SET SESSION wsrep_osu_method=NBO; + +--error ER_CANT_DROP_FIELD_OR_KEY +ALTER TABLE t1 LOCK=SHARED, DROP PRIMARY KEY; + +--source ../include/galera_check_voting_recovery.inc + +--connection node_1 +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; + +--connection node_2 +CALL mtr.add_suppression("inconsistent with group"); + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3 +CALL mtr.add_suppression("Slave SQL: Error"); diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_success.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_success.cnf new file mode 100644 index 00000000000..e255e1d527e --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_success.cnf @@ -0,0 +1,4 @@ +!include ../galera_3nodes.cnf + +[mysqld] +wsrep-ignore-apply-errors=0 diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_success.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_success.test new file mode 100644 index 00000000000..3fca44efa2a --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_majority_success.test @@ -0,0 +1,38 @@ +# +# This test has the master in the majority when an +# NBO DDL succeeds on master +# + +--source include/galera_cluster.inc +--source include/big_test.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +# Introduce inconsistency on node #2 +--connection node_2 +SET SESSION wsrep_on=OFF; +ALTER TABLE t1 ADD PRIMARY KEY (f1); +SET SESSION wsrep_on=ON; + +--connection node_1 +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1); + +--source ../include/galera_check_voting_recovery.inc + +--connection node_1 +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t1; + +--connection node_2 +CALL mtr.add_suppression("Slave SQL: Error"); +CALL mtr.add_suppression("Inconsistent by consensus"); +CALL mtr.add_suppression("Failed to execute TOI action"); +CALL mtr.add_suppression("Non-blocking operation end failed"); + +--let $galera_connection_name = node_3 +--let $galera_server_number = 3 +--source include/galera_connect.inc +--connection node_3 +--source include/galera_wait_ready.inc diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_failure.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_failure.cnf new file mode 100644 index 00000000000..e255e1d527e --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_failure.cnf @@ -0,0 +1,4 @@ +!include ../galera_3nodes.cnf + +[mysqld] +wsrep-ignore-apply-errors=0 diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_failure.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_failure.test new file mode 100644 index 00000000000..151ae4f6ad8 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_failure.test @@ -0,0 +1,35 @@ +# +# This test has the master (node #2) in the minority when an +# NBO DDL fails on master +# + +--source include/galera_cluster.inc +--source include/big_test.inc + +--connection node_2 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +SET SESSION wsrep_on=OFF; +ALTER TABLE t1 ADD PRIMARY KEY (f1); +SET SESSION wsrep_on=ON; + +SET SESSION wsrep_OSU_method='NBO'; + +--error ER_MULTIPLE_PRI_KEY +ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1); + +--source ../include/galera_check_voting_recovery.inc + +--connection node_1 +DROP TABLE t1; +CALL mtr.add_suppression("SYNC message from member"); + +--connection node_2 +CALL mtr.add_suppression("Inconsistent by consensus"); +CALL mtr.add_suppression("Failed to execute TOI action"); +CALL mtr.add_suppression("TO isolation end failed"); +CALL mtr.add_suppression("SYNC message from member"); + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3 +CALL mtr.add_suppression("SYNC message from member"); diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_success.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_success.cnf new file mode 100644 index 00000000000..e255e1d527e --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_success.cnf @@ -0,0 +1,4 @@ +!include ../galera_3nodes.cnf + +[mysqld] +wsrep-ignore-apply-errors=0 diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_success.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_success.test new file mode 100644 index 00000000000..b6a971a8e01 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_minority_success.test @@ -0,0 +1,41 @@ +# +# This test has the master (node #2) in the minority when an +# NBO DDL succeeds on master +# + +--source include/galera_cluster.inc +--source include/big_test.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +SET SESSION wsrep_on=OFF; +ALTER TABLE t1 ADD PRIMARY KEY (f1); +SET SESSION wsrep_on=ON; + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3 +SET SESSION wsrep_on=OFF; +ALTER TABLE t1 ADD PRIMARY KEY (f1); +SET SESSION wsrep_on=ON; + +# Node #2 goes non-prim because it is in the minority +--connection node_2 +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1); + +--source ../include/galera_check_voting_recovery.inc + +--connection node_2 +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t1; + +--connection node_1 +CALL mtr.add_suppression("Slave SQL: Error"); + +--connection node_2 +CALL mtr.add_suppression("inconsistent with group"); + +--connection node_3 +--source include/galera_wait_ready.inc +CALL mtr.add_suppression("Slave SQL: Error"); diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_non_prim_failure.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_non_prim_failure.test new file mode 100644 index 00000000000..79ff032f02b --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_non_prim_failure.test @@ -0,0 +1,92 @@ +# +# Test the case where a master node (node #2) goes non-primary while a DDL is running +# The DDL times out and the node leaves the cluster, to rejoin via SST. +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc +--source include/big_test.inc + +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +# Issue a DDL + +--connection node_2 +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; +SET SESSION wsrep_osu_method=NBO; +SET SESSION lock_wait_timeout=2; +--send ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD COLUMN f2 INTEGER; + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now'; +--source include/wait_condition.inc + +# Isolate the master (node #2) + +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; + +--connection node_1 +--source include/wait_until_connected_again.inc +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT COUNT(*) = 2 FROM wsrep_schema.members; +--source include/wait_condition.inc + +# Confirm that the DDL remains blocked in NBO + +--connection node_2a +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; + +SET SESSION wsrep_on=OFF; +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'acquiring total order isolation for NBO end' +--source include/wait_condition.inc + +# DDL should now return a failure + +--connection node_2 +--error ER_ERROR_DURING_COMMIT +--reap + +# Node #2 is now non-prim + +--connection node_2 +SET SESSION wsrep_sync_wait = 0; +SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; + +--connection node_1 +INSERT INTO t1 VALUES (2,2); + +--connection node_2 +# So we restart it to force SST +SET SESSION wsrep_on = OFF; +--source include/restart_mysqld.inc +--source include/wait_until_connected_again.inc + +# Confirm that the nodes are identical + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +SHOW CREATE TABLE t1; +SELECT COUNT(*) = 2 FROM t1; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status' +--source include/wait_condition.inc + +SHOW CREATE TABLE t1; +SELECT COUNT(*) = 2 FROM t1; + +--connection node_1 +DROP TABLE t1; + +--connection node_2 +CALL mtr.add_suppression("Lock wait timeout while waiting NBO end to replicate"); +CALL mtr.add_suppression("Failed to acquire total order isolation for non-blocking DDL end event, provider returned error code 6"); +CALL mtr.add_suppression("This will leave database in inconsistent state since DDL execution cannot be terminated in order"); + diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_non_prim_success.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_non_prim_success.test new file mode 100644 index 00000000000..995828b3ca1 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_master_non_prim_success.test @@ -0,0 +1,80 @@ +# +# Test the case where a master node (node #2) goes non-primary while a DDL is running +# The non-prim situation is resolved in time and the DDL completes successfully +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +# Issue a DDL + +--connection node_2 +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; +SET SESSION wsrep_osu_method=NBO; +--send ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1); + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now'; +--source include/wait_condition.inc + +# Isolate the master (node #2) + +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; + +--connection node_1 +--source include/wait_until_connected_again.inc +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT COUNT(*) = 2 FROM wsrep_schema.members; +--source include/wait_condition.inc + +# Confirm that the DDL remains blocked in NBO + +--connection node_2a +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; + +SET SESSION wsrep_on=OFF; +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'acquiring total order isolation for NBO end' +--source include/wait_condition.inc + +# Reconnect node #2 to cluster + +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; +--let $wait_condition = SELECT COUNT(*) = 3 FROM wsrep_schema.members; +--source include/wait_condition.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment' +--source include/wait_condition.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready' +--source include/wait_condition.inc + +--connection node_1 +--source include/wait_until_connected_again.inc +--let $wait_condition = SELECT COUNT(*) = 3 FROM wsrep_schema.members; +--source include/wait_condition.inc + +# DDL should now be complete + +--connection node_2 +--reap + +# Confirm that the nodes are identical + +--connection node_1 +SHOW CREATE TABLE t1; +SELECT COUNT(*) = 1 FROM t1; + +--connection node_2 +SHOW CREATE TABLE t1; +--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready' +--source include/wait_condition.inc +SELECT COUNT(*) = 1 FROM t1; + +--connection node_1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_shutdown_slave_ist.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_shutdown_slave_ist.test new file mode 100644 index 00000000000..58f7f00ed71 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_shutdown_slave_ist.test @@ -0,0 +1,66 @@ +# +# This test kills a slave while a DDL is being applied there +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/big_test.inc + +--let $galera_connection_name = node_3 +--let $galera_server_number = 3 +--source include/galera_connect.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +--connection node_3 +# Set so that the applier thread will block in mysql_alter_table() +--let $debug_orig = `SELECT @@debug` +SET GLOBAL debug = 'd,sync.alter_opened_table'; + +--connection node_1 +SET SESSION wsrep_osu_method=NBO; +--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER; + +--connection node_3 +# Wait until the ALTER above has arrived on the slave and has blocked in the applier thread +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER' AND STATE = 'debug sync point: now'; +--source include/wait_condition.inc + +# Shutdown the slave (node #3) +--source include/shutdown_mysqld.inc +--sleep 5 + +# Wait until node #3 is completely out of the cluster +--connection node_2 +--source include/wait_until_connected_again.inc + +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +INSERT INTO t1 VALUES (1,2); + +# Restart node #3 +--connection node_3 +--source include/start_mysqld.inc +--sleep 10 + +# Check that all nodes have the same view of the database +--source include/wait_until_connected_again.inc +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 1 FROM t1; +CALL mtr.add_suppression("WSREP: no corresponding NBO begin found for NBO end source"); + +--connection node_2 +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 1 FROM t1; +CALL mtr.add_suppression("WSREP: gcs_caused() returned -1 \\(Operation not permitted\\)"); + +--connection node_1 +--reap +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 1 FROM t1; + +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_slave_non_prim.test b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_slave_non_prim.test new file mode 100644 index 00000000000..d4f3a4ffedd --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_nbo_slave_non_prim.test @@ -0,0 +1,69 @@ +# +# Test the case where a slave node goes non-primary while a DDL is running +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +--connection node_2 +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; + +--connection node_1 +SET SESSION wsrep_osu_method=NBO; +--send ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1); + +--connection node_2 +SET SESSION wsrep_sync_wait=0; + +# Wait for the ALTER to block in sync point +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now'; +--source include/wait_condition.inc + +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +--source include/wait_until_connected_again.inc +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT COUNT(*) = 2 FROM wsrep_schema.members; +--source include/wait_condition.inc + +--connection node_1 +--reap + +--connection node_2 +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; + +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; + +--connection node_1 +--source include/wait_until_connected_again.inc +--source include/galera_wait_ready.inc +--let $wait_condition = SELECT COUNT(*) = 3 FROM wsrep_schema.members; +--source include/wait_condition.inc + +SHOW CREATE TABLE t1; +SELECT COUNT(*) = 1 FROM t1; + +--connection node_2 +--source include/wait_until_connected_again.inc +--source include/galera_wait_ready.inc +SELECT COUNT(*) = 3 FROM wsrep_schema.members; +SHOW CREATE TABLE t1; +SELECT COUNT(*) = 1 FROM t1; + +--connection node_1 +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; +CALL mtr.add_suppression("gcs_caused\\(\\) returned -1"); + +--let $galera_connection_name = node_3 +--let $galera_server_number = 3 +--source include/galera_connect.inc +--connection node_3 +--source include/galera_wait_ready.inc diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_toi_vote.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera_toi_vote.cnf new file mode 100644 index 00000000000..e255e1d527e --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_toi_vote.cnf @@ -0,0 +1,4 @@ +!include ../galera_3nodes.cnf + +[mysqld] +wsrep-ignore-apply-errors=0 diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_toi_vote.test b/mysql-test/suite/galera_3nodes_ee/t/galera_toi_vote.test new file mode 100644 index 00000000000..23cfcd036a0 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_toi_vote.test @@ -0,0 +1,63 @@ +# +# This test tests that TOI failure on 2 nodes (master and slave) for the +# same reason, wins over success on a third slave. +# In particular this tests that master and slave TOI cast the same vote for +# the same error +# +--source include/galera_3nodes.inc +--source include/have_innodb.inc + +# create inconsistency on node 3 +--connection node_3 +SET GLOBAL wsrep_on=OFF; +DROP SCHEMA test; + +# This should fail on nodes 1 and 2 and succeed on node 3 +--connection node_1 +--error ER_DB_CREATE_EXISTS +CREATE SCHEMA test; + +--connection node_1 +SET SESSION wsrep_sync_wait=0; +# wait for node 3 to drop from the cluster +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +--source include/wait_condition.inc + +--connection node_2 +SET SESSION wsrep_sync_wait=0; +# wait for node 3 to drop from the cluster +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +--source include/wait_condition.inc + +--connection node_3 +SET SESSION wsrep_sync_wait=0; +--let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +--source include/wait_condition.inc + +# reconnect node 3, since it failed +--connection node_3 +--source include/kill_galera.inc +--sleep 1 +--source include/start_mysqld.inc + +--connection node_1 +CALL mtr.add_suppression("Inconsistent by consensus."); +CALL mtr.add_suppression("Error_code: 1007"); +CALL mtr.add_suppression("WSREP: Failed to apply trx: source: "); +CALL mtr.add_suppression("WSREP: Failed to apply app buffer: seqno: 4, code: "); +CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster..."); + +--connection node_2 +CALL mtr.add_suppression("Inconsistent by consensus."); +CALL mtr.add_suppression("Error_code: 1007"); +CALL mtr.add_suppression("WSREP: Failed to apply trx: source: "); +CALL mtr.add_suppression("WSREP: Failed to apply app buffer: seqno: 4, code: "); +CALL mtr.add_suppression("WSREP: Node consistency compromized, leaving cluster..."); + +--connection node_3 +CALL mtr.add_suppression("inconsistent with group"); + diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_vote_rejoin_mysqldump.cnf b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_rejoin_mysqldump.cnf new file mode 100644 index 00000000000..e255e1d527e --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_rejoin_mysqldump.cnf @@ -0,0 +1,4 @@ +!include ../galera_3nodes.cnf + +[mysqld] +wsrep-ignore-apply-errors=0 diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_vote_rejoin_mysqldump.test b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_rejoin_mysqldump.test new file mode 100644 index 00000000000..bc696ed6896 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_rejoin_mysqldump.test @@ -0,0 +1,80 @@ +# +# Test that mysqldump SST is possible after a vote without a cluster restart +# + +--source include/galera_cluster.inc +--source suite/galera/include/galera_sst_set_mysqldump.inc + + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +# Introduce inconsistency on node #2 + +--connection node_2 +--let $wsrep_cluster_address_node2 = `SELECT @@wsrep_cluster_address` +SET SESSION wsrep_on=OFF; +ALTER TABLE t1 ADD PRIMARY KEY (f1); +SET SESSION wsrep_on=ON; + +# Run DDL that will fail on nodes #1 and #3 but succeed on node #2 + +--connection node_1 +--error ER_CANT_DROP_FIELD_OR_KEY +ALTER TABLE t1 LOCK=SHARED, DROP PRIMARY KEY; + +# Nodes #1 and #3 remain in the cluster + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; + +# Node #2 is kicked out + +--connection node_2 +SET SESSION wsrep_on=OFF; +SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +SET SESSION wsrep_on=ON; + +# Restore cluster + +--disable_query_log +--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_node2' +--enable_query_log +--enable_reconnect + +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; + +# Confirm that the table is now identical throughout + +--connection node_1 +SHOW CREATE TABLE t1; + +--connection node_2 +SET SESSION wsrep_on=OFF; +--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +--source include/wait_condition.inc +--source include/galera_wait_ready.inc +SET SESSION wsrep_on=ON; + +SHOW CREATE TABLE t1; +SELECT COUNT(*) = 0 FROM t1; +CALL mtr.add_suppression("is inconsistent with group"); + +--connection node_3 +SHOW CREATE TABLE t1; +DROP TABLE t1; +CALL mtr.add_suppression("Slave SQL: Error 'Can't DROP 'PRIMARY'; check that column/key exists'"); + +--connection node_1 +--source suite/galera/include/galera_sst_restore.inc diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_vote_sr-master.opt b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_sr-master.opt new file mode 100644 index 00000000000..196498bb9fa --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_sr-master.opt @@ -0,0 +1,2 @@ +--wsrep-ignore-apply-errors=0 + diff --git a/mysql-test/suite/galera_3nodes_ee/t/galera_vote_sr.test b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_sr.test new file mode 100644 index 00000000000..7655c818de6 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/galera_vote_sr.test @@ -0,0 +1,87 @@ +# +# Test voting while an SR transaction is in progress +# + +--source include/galera_cluster.inc +--source include/big_test.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 BLOB) ENGINE=InnoDB; + +# Introduce inconsistency +--connection node_2 +SET SESSION wsrep_on=OFF; +INSERT INTO t1 VALUES (5, 'X'); +SET SESSION wsrep_on=ON; +DELETE FROM t1 WHERE f1 = 2; + +# Perform an SR transaction that will hit the inconsistency +--connection node_1 +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size = 131070; +START TRANSACTION; +INSERT INTO t1 VALUES (1, REPEAT('A', 65535)); +INSERT INTO t1 VALUES (2, REPEAT('A', 65535)); +INSERT INTO t1 VALUES (3, REPEAT('A', 65535)); +INSERT INTO t1 VALUES (4, REPEAT('A', 65535)); +INSERT INTO t1 VALUES (5, REPEAT('A', 65535)); +COMMIT; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +# Perform another SR transaction in order to have stuff in the wsrep_schema.SR table +START TRANSACTION; +INSERT INTO t1 VALUES (11, REPEAT('A', 65535)); +INSERT INTO t1 VALUES (12, REPEAT('A', 65535)); +INSERT INTO t1 VALUES (13, REPEAT('A', 65535)); +INSERT INTO t1 VALUES (14, REPEAT('A', 65535)); +INSERT INTO t1 VALUES (15, REPEAT('A', 65535)); + +# Node #2 has dropped from the cluster due to voting +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +# Bring node #2 back via SST +--connection node_2 +SET SESSION wsrep_on=OFF; +--source include/shutdown_mysqld.inc + +--sleep 10 + +--echo Starting mysqld +--source include/start_mysqld.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +--source include/wait_condition.inc + +# Node #2 should have some entries in its SR table post-restart +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +# Commit second SR transaction +--connection node_1 +COMMIT; + +# Confirm that all nodes are identical +--connection node_1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +SELECT COUNT(*) = 10 FROM t1; + +--connection node_2 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +SELECT COUNT(*) = 10 FROM t1; +CALL mtr.add_suppression("Slave SQL: Could not execute Write_rows event on table test.t1; Duplicate entry '5' for key 'PRIMARY'"); +CALL mtr.add_suppression("Write_rows apply failed"); +CALL mtr.add_suppression("Inconsistent by consensus"); +CALL mtr.add_suppression("no THD for trx"); + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +SELECT COUNT(*) = 10 FROM t1; + +--connection node_1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_ee/t/mysql-wsrep-features#131.test b/mysql-test/suite/galera_3nodes_ee/t/mysql-wsrep-features#131.test new file mode 100644 index 00000000000..95bc16dd42b --- /dev/null +++ b/mysql-test/suite/galera_3nodes_ee/t/mysql-wsrep-features#131.test @@ -0,0 +1,39 @@ +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +SET SESSION wsrep_osu_method=NBO; + +--connection node_2 +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; + +--connection node_1 +--send ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1); + +--connection node_2 +SET SESSION wsrep_sync_wait=0; + +# Wait for the ALTER to block in sync point +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now'; +--source include/wait_condition.inc + +--send INSERT INTO t1 VALUES (1); + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a + +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; + +--connection node_2 +--error ER_DUP_ENTRY +--reap + + +--connection node_1 +--reap +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/galera_3nodes.cnf b/mysql-test/suite/galera_3nodes_sr/galera_3nodes.cnf new file mode 100644 index 00000000000..62c8214b8f2 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/galera_3nodes.cnf @@ -0,0 +1 @@ +!include ../galera_3nodes/galera_3nodes.cnf diff --git a/mysql-test/suite/galera_3nodes_sr/my.cnf b/mysql-test/suite/galera_3nodes_sr/my.cnf new file mode 100644 index 00000000000..bb25b95ceea --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/my.cnf @@ -0,0 +1 @@ +!include galera_3nodes.cnf diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-336.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-336.result new file mode 100644 index 00000000000..ac3813176c9 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-336.result @@ -0,0 +1,26 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) > 0 FROM t1; +COUNT(*) > 0 +1 +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; +SET SESSION wsrep_sync_wait=0; +INSERT INTO t1 VALUES (2); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +COMMIT; +ERROR 08S01: WSREP has not yet prepared node for application use +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; +DROP TABLE t1; +CALL mtr.add_suppression("replication aborted"); +CALL mtr.add_suppression("WSREP: fragment replication failed: 3"); +CALL mtr.add_suppression("WSREP: failed to send SR rollback for "); diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-582.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-582.result new file mode 100644 index 00000000000..68a8fde0abc --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-582.result @@ -0,0 +1,23 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SELECT COUNT(*) FROM wsrep_schema.SR; +COUNT(*) +5 +SELECT COUNT(*) FROM wsrep_schema.SR; +COUNT(*) +5 +COMMIT; +SELECT COUNT(*) FROM t1; +COUNT(*) +5 +SELECT COUNT(*) FROM t1; +COUNT(*) +5 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-606.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-606.result new file mode 100644 index 00000000000..03c7963c6d5 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-606.result @@ -0,0 +1,23 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (20); +INSERT INTO t1 VALUES (21); +INSERT INTO t1 VALUES (22); +INSERT INTO t1 VALUES (23); +INSERT INTO t1 VALUES (24); +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR; +COUNT(DISTINCT node_uuid) = 1 +0 +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM t1; +f1 +COMMIT; +SELECT * FROM t1; +f1 +DROP TABLE t1; +CALL mtr.add_suppression("WSREP: failed to send SR rollback for "); diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-609.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-609.result new file mode 100644 index 00000000000..52544166e29 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-609.result @@ -0,0 +1,20 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size=1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); +SET SESSION wsrep_trx_fragment_size=1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20); +INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +INSERT INTO t1 VALUES (31),(32),(33); +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +0 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +0 +COMMIT; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-810A.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-810A.result new file mode 100644 index 00000000000..9064030aa89 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-810A.result @@ -0,0 +1,256 @@ +SET GLOBAL debug="d,crash_last_fragment_commit_before_fragment_removal"; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'); +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary'); +INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'); +INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary'); +crash_last_fragment_commit_before_fragment_removal +COMMIT; +Got one of the listed errors +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR; +COUNT(DISTINCT node_uuid) = 1 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR; +COUNT(DISTINCT node_uuid) = 1 +1 +COMMIT; +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET GLOBAL debug = ''; +SET GLOBAL debug="d,crash_last_fragment_commit_after_fragment_removal"; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'); +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary'); +INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'); +INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary'); +crash_last_fragment_commit_after_fragment_removal +COMMIT; +Got one of the listed errors +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR; +COUNT(DISTINCT node_uuid) = 1 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR; +COUNT(DISTINCT node_uuid) = 1 +1 +COMMIT; +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET GLOBAL debug = ''; +SET GLOBAL debug="d,crash_replicate_fragment_success"; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'); +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary'); +INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'); +INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary'); +crash_replicate_fragment_success +COMMIT; +Got one of the listed errors +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR; +COUNT(DISTINCT node_uuid) = 1 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR; +COUNT(DISTINCT node_uuid) = 1 +1 +COMMIT; +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET GLOBAL debug = ''; +SET GLOBAL debug="d,crash_replicate_fragment_after_certify"; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'); +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary'); +INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'); +INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary'); +crash_replicate_fragment_after_certify +COMMIT; +Got one of the listed errors +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR; +COUNT(DISTINCT node_uuid) = 1 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR; +COUNT(DISTINCT node_uuid) = 1 +1 +COMMIT; +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET GLOBAL debug = ''; +SET GLOBAL debug="d,crash_replicate_fragment_before_certify"; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'); +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary'); +INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'); +INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary'); +crash_replicate_fragment_before_certify +COMMIT; +Got one of the listed errors +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR; +COUNT(DISTINCT node_uuid) = 1 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR; +COUNT(DISTINCT node_uuid) = 1 +1 +COMMIT; +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET GLOBAL debug = ''; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-810B.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-810B.result new file mode 100644 index 00000000000..a0f002ac627 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-810B.result @@ -0,0 +1,100 @@ +SET GLOBAL debug="d,crash_apply_cb_before_append_frag"; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary'); +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'); +INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary'); +INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'); +COMMIT; +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR; +COUNT(DISTINCT node_uuid) = 1 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR; +COUNT(DISTINCT node_uuid) = 1 +1 +COMMIT; +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET GLOBAL debug = ''; +SET GLOBAL debug="d,crash_apply_cb_after_append_frag"; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary'); +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'); +INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary'); +INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'); +COMMIT; +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR; +COUNT(DISTINCT node_uuid) = 1 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR; +COUNT(DISTINCT node_uuid) = 1 +1 +COMMIT; +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET GLOBAL debug = ''; +CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member"); +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-810C.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-810C.result new file mode 100644 index 00000000000..cddd8918a2a --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-810C.result @@ -0,0 +1,177 @@ +SET GLOBAL debug="d,crash_commit_cb_last_fragment_commit_success"; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary'); +SET SESSION wsrep_trx_fragment_size=1; +INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'); +SELECT 1 FROM t1; +Got one of the listed errors +SELECT * FROM wsrep_schema.SR; +node_uuid trx_id seqno flags frag +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT * FROM wsrep_schema.SR; +node_uuid trx_id seqno flags frag +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT * FROM wsrep_schema.SR; +node_uuid trx_id seqno flags frag +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET GLOBAL debug="d,crash_commit_cb_before_last_fragment_commit"; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary'); +SET SESSION wsrep_trx_fragment_size=1; +INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'); +SELECT 1 FROM t1; +Got one of the listed errors +SELECT * FROM wsrep_schema.SR; +node_uuid trx_id seqno flags frag +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT * FROM wsrep_schema.SR; +node_uuid trx_id seqno flags frag +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT * FROM wsrep_schema.SR; +node_uuid trx_id seqno flags frag +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET GLOBAL debug="d,crash_apply_cb_after_fragment_removal"; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary'); +SET SESSION wsrep_trx_fragment_size=1; +INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'); +SELECT 1 FROM t1; +Got one of the listed errors +SELECT * FROM wsrep_schema.SR; +node_uuid trx_id seqno flags frag +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT * FROM wsrep_schema.SR; +node_uuid trx_id seqno flags frag +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT * FROM wsrep_schema.SR; +node_uuid trx_id seqno flags frag +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET GLOBAL debug="d,crash_apply_cb_before_fragment_removal"; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE = InnoDB; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES ('secondary'),('secondary'),('secondary'),('secondary'),('secondary'); +SET SESSION wsrep_trx_fragment_size=1; +INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'),('primary'); +SELECT 1 FROM t1; +Got one of the listed errors +SELECT * FROM wsrep_schema.SR; +node_uuid trx_id seqno flags frag +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT * FROM wsrep_schema.SR; +node_uuid trx_id seqno flags frag +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT * FROM wsrep_schema.SR; +node_uuid trx_id seqno flags frag +SELECT COUNT(*) > 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-817.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-817.result new file mode 100644 index 00000000000..35a96650037 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-817.result @@ -0,0 +1,33 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +INSERT INTO t1 VALUES (6); +INSERT INTO t1 VALUES (7); +SET SESSION wsrep_sync_wait = 0; +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; +SET SESSION wsrep_on = OFF; +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-832.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-832.result new file mode 100644 index 00000000000..7680f0380af --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-832.result @@ -0,0 +1,15 @@ +SET GLOBAL debug="d,crash_last_fragment_commit_after_fragment_removal"; +CREATE TABLE t1 (f1 VARCHAR(30)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'); +COMMIT; +ERROR HY000: Lost connection to MySQL server during query +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_isolate_master.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_isolate_master.result new file mode 100644 index 00000000000..5ecf1b6ec00 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_isolate_master.result @@ -0,0 +1,62 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) > 0 FROM t1; +COUNT(*) > 0 +1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +COMMIT; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +CALL mtr.add_suppression("failed to send SR rollback for"); +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_join_slave.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_join_slave.result new file mode 100644 index 00000000000..eb539eba919 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_join_slave.result @@ -0,0 +1,25 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +INSERT INTO t1 VALUES (6); +INSERT INTO t1 VALUES (7); +INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (9); +INSERT INTO t1 VALUES (10); +COMMIT; +SELECT COUNT(*) = 10 FROM t1; +COUNT(*) = 10 +1 +SELECT COUNT(*) = 10 FROM t1; +COUNT(*) = 10 +1 +SELECT COUNT(*) = 10 FROM t1; +COUNT(*) = 10 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_master.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_master.result new file mode 100644 index 00000000000..dcf291bacc7 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_master.result @@ -0,0 +1,22 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +Killing server ... +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +INSERT INTO t1 VALUES (1); +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply.result new file mode 100644 index 00000000000..a849a44832e --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply.result @@ -0,0 +1,38 @@ +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +Killing server ... +INSERT INTO t1 VALUES (6); +INSERT INTO t1 VALUES (7); +INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (9); +INSERT INTO t1 VALUES (10); +INSERT INTO t1 VALUES (11); +INSERT INTO t1 VALUES (12); +INSERT INTO t1 VALUES (13); +INSERT INTO t1 VALUES (14); +INSERT INTO t1 VALUES (15); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 15 FROM wsrep_schema.SR; +COUNT(*) = 15 +1 +COMMIT; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SELECT COUNT(*) = 15 FROM t1; +COUNT(*) = 15 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; +CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member"); diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply_rollback.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply_rollback.result new file mode 100644 index 00000000000..7bc36c3d0af --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply_rollback.result @@ -0,0 +1,44 @@ +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +Killing server ... +INSERT INTO t1 VALUES (6); +INSERT INTO t1 VALUES (7); +INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (9); +INSERT INTO t1 VALUES (10); +INSERT INTO t1 VALUES (11); +INSERT INTO t1 VALUES (12); +INSERT INTO t1 VALUES (13); +INSERT INTO t1 VALUES (14); +INSERT INTO t1 VALUES (15); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 15 FROM wsrep_schema.SR; +COUNT(*) = 15 +1 +ROLLBACK; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply_rollback2.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply_rollback2.result new file mode 100644 index 00000000000..8b015c26977 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply_rollback2.result @@ -0,0 +1,31 @@ +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +Killing server ... +INSERT INTO t1 VALUES (6); +ROLLBACK; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_before_apply.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_before_apply.result new file mode 100644 index 00000000000..285421c4d25 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_before_apply.result @@ -0,0 +1,27 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +CREATE TABLE t2 (f1 INTEGER); +LOCK TABLE t2 WRITE; +INSERT INTO t2 VALUES (1); +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +Killing server ... +COMMIT; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera_3nodes_sr/r/galera_sr_threeway_split.result b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_threeway_split.result new file mode 100644 index 00000000000..0daf6484d04 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_threeway_split.result @@ -0,0 +1,84 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (10); +INSERT INTO t1 VALUES (11); +INSERT INTO t1 VALUES (12); +INSERT INTO t1 VALUES (13); +INSERT INTO t1 VALUES (14); +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (200); +INSERT INTO t1 VALUES (201); +INSERT INTO t1 VALUES (202); +INSERT INTO t1 VALUES (203); +INSERT INTO t1 VALUES (204); +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (300); +INSERT INTO t1 VALUES (301); +INSERT INTO t1 VALUES (302); +INSERT INTO t1 VALUES (303); +INSERT INTO t1 VALUES (304); +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +INSERT INTO t1 VALUES (20); +INSERT INTO t1 VALUES (21); +INSERT INTO t1 VALUES (22); +INSERT INTO t1 VALUES (23); +INSERT INTO t1 VALUES (24); +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR; +COUNT(DISTINCT node_uuid) = 1 +1 +wsrep_gcomm_uuid_match +1 +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR; +COUNT(DISTINCT node_uuid) = 1 +1 +wsrep_gcomm_uuid_match +1 +INSERT INTO t1 VALUES (30); +INSERT INTO t1 VALUES (31); +INSERT INTO t1 VALUES (32); +INSERT INTO t1 VALUES (33); +INSERT INTO t1 VALUES (34); +COMMIT; +SELECT COUNT(*) = 15, MIN(f1) = 10, MAX(f1) = 34 FROM t1; +COUNT(*) = 15 MIN(f1) = 10 MAX(f1) = 34 +1 1 1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +COMMIT; +SELECT COUNT(*) = 15, MIN(f1) = 10, MAX(f1) = 34 FROM t1; +COUNT(*) = 15 MIN(f1) = 10 MAX(f1) = 34 +1 1 1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +COMMIT; +SELECT COUNT(*) = 15, MIN(f1) = 10, MAX(f1) = 34 FROM t1; +COUNT(*) = 15 MIN(f1) = 10 MAX(f1) = 34 +1 1 1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +DROP TABLE t1; +CALL mtr.add_suppression("WSREP: failed to send SR rollback for "); +CALL mtr.add_suppression("WSREP: failed to send SR rollback for "); +CALL mtr.add_suppression("WSREP: failed to send SR rollback for "); diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-336.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-336.test new file mode 100644 index 00000000000..ea8bed454ca --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-336.test @@ -0,0 +1,47 @@ +--source include/galera_cluster.inc + +--connection node_2 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1); + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +--connection node_1 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) > 0 FROM t1; + +--connection node_2a +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; +SET SESSION wsrep_sync_wait=0; + +--connection node_2 +--error ER_LOCK_DEADLOCK +INSERT INTO t1 VALUES (2); +--error ER_UNKNOWN_COM_ERROR +COMMIT; + +--connection node_2a +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +--source include/wait_condition.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +--source include/wait_condition.inc +DROP TABLE t1; + +CALL mtr.add_suppression("replication aborted"); +CALL mtr.add_suppression("WSREP: fragment replication failed: 3"); +CALL mtr.add_suppression("WSREP: failed to send SR rollback for "); + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3 +--source include/galera_wait_ready.inc diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-582.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-582.test new file mode 100644 index 00000000000..ab029594f4d --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-582.test @@ -0,0 +1,39 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +--connection node_2 +--source include/shutdown_mysqld.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connection node_2 +--source include/start_mysqld.inc +--source include/wait_until_connected_again.inc +--source include/galera_wait_ready.inc + +SELECT COUNT(*) FROM wsrep_schema.SR; + +--connection node_1 +SELECT COUNT(*) FROM wsrep_schema.SR; +COMMIT; +SELECT COUNT(*) FROM t1; + +--connection node_2 +SELECT COUNT(*) FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-606.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-606.test new file mode 100644 index 00000000000..34d8ec55f1a --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-606.test @@ -0,0 +1,80 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test the case where the cluster splits 3 ways. +# The master transitions to a non-prim view and back to prim. Its ongoing +# should fail to commit. +# + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +--connection node_2 +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (20); +INSERT INTO t1 VALUES (21); +INSERT INTO t1 VALUES (22); +INSERT INTO t1 VALUES (23); +INSERT INTO t1 VALUES (24); + +--connection node_1 +--let $wait_condition = SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR +--source include/wait_condition.inc + +# +# Isolate node_2 into a separate non-primary component +# + +--connection node_2a +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +--disable_query_log +SET WSREP_ON=OFF; +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +SET WSREP_ON=ON; +--enable_query_log + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +# +# Confirm that node_1 has no transactions in SR table +# + +--let $wait_condition = SELECT COUNT(DISTINCT node_uuid) = 0 FROM wsrep_schema.SR; +--source include/wait_condition.inc + +# +# Restore cluster +# + +--connection node_2a +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +--source include/galera_wait_ready.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +--connection node_1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR; + +--connection node_2 +--error ER_LOCK_DEADLOCK +COMMIT; +SELECT * FROM t1; +COMMIT; + +--connection node_1 +SELECT * FROM t1; + +DROP TABLE t1; + +--connection node_2 +CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
\ No newline at end of file diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-609.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-609.test new file mode 100644 index 00000000000..6e5da4bf349 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-609.test @@ -0,0 +1,30 @@ +# +# GCF-609 SR: Assertion wsrep_apply_cb on slave after master causes a duplicate key error +# + +--source include/galera_cluster.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +--connection node_1 +SET SESSION wsrep_trx_fragment_size=1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); + +--connection node_2 +SET SESSION wsrep_trx_fragment_size=1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20); +--error ER_LOCK_DEADLOCK +INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20); +INSERT INTO t1 VALUES (31),(32),(33); + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COMMIT; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-810A.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-810A.test new file mode 100644 index 00000000000..38d95556e48 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-810A.test @@ -0,0 +1,137 @@ +# +# Exercise the crash points which crash the server at various points important to SR +# + +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_debug_sync.inc + +--connect node_2_check, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connect node_3_check, 127.0.0.1, root, , test, $NODE_MYPORT_3 + +# +# crash_last_fragment_commit_before_fragment_removal +# + +--connection node_2 +--enable_reconnect +SET GLOBAL debug="d,crash_last_fragment_commit_before_fragment_removal"; +--source suite/galera_3nodes/include/galera_expect_node_crash.inc +--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes.inc + +--echo crash_last_fragment_commit_before_fragment_removal + +--connection node_2 +--error 2006,2013 +COMMIT; + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE variable_name = 'wsrep_cluster_size' +--source include/wait_condition.inc + +--connection node_2 +--source include/start_mysqld.inc +--source suite/galera_3nodes/include/galera_sr_crash_post_check.inc + +# +# crash_last_fragment_commit_after_fragment_removal +# + +--connection node_2 +SET GLOBAL debug="d,crash_last_fragment_commit_after_fragment_removal"; +--source suite/galera_3nodes/include/galera_expect_node_crash.inc +--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes.inc + +--echo crash_last_fragment_commit_after_fragment_removal + +--connection node_2 +--error 2006,2013 +COMMIT; + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE variable_name = 'wsrep_cluster_size' +--source include/wait_condition.inc + +--connection node_2 +--source include/start_mysqld.inc +--source suite/galera_3nodes/include/galera_sr_crash_post_check.inc + +# +# crash_last_fragment_commit_success +# +# Case crash_last_fragment_commit_success is commented out, +# the changes will be visible on slave due to succesful commit, +# so the galera_sr_crash_post_check will fail. +# + +# --connection node_2 +# SET GLOBAL debug="d,crash_last_fragment_commit_success"; +# --source suite/galera_3nodes/include/galera_expect_node_crash.inc +# --source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes.inc + +# --echo crash_last_fragment_commit_success + +# --connection node_2 +# --error 2006,2013 +# COMMIT; + +# --source include/start_mysqld.inc +# --source suite/galera_3nodes/include/galera_sr_crash_post_check.inc + +# +# crash_replicate_fragment_success +# + +--connection node_2 +SET GLOBAL debug="d,crash_replicate_fragment_success"; +--source suite/galera_3nodes/include/galera_expect_node_crash.inc +--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes.inc + +--echo crash_replicate_fragment_success + +--connection node_2 +--error 2006,2013 +COMMIT; + +--source include/start_mysqld.inc +--source suite/galera_3nodes/include/galera_sr_crash_post_check.inc + +# +# crash_replicate_fragment_after_certify +# + +--connection node_2 +SET GLOBAL debug="d,crash_replicate_fragment_after_certify"; +--source suite/galera_3nodes/include/galera_expect_node_crash.inc +--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes.inc + +--echo crash_replicate_fragment_after_certify + +--connection node_2 +--error 2006,2013 +COMMIT; + +--source include/start_mysqld.inc +--source suite/galera_3nodes/include/galera_sr_crash_post_check.inc + +# +# crash_replicate_fragment_before_certify +# + +--connection node_2 +SET GLOBAL debug="d,crash_replicate_fragment_before_certify"; +--source suite/galera_3nodes/include/galera_expect_node_crash.inc +--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes.inc + +--echo crash_replicate_fragment_before_certify + +--connection node_2 +--error 2006,2013 +COMMIT; + +--source include/start_mysqld.inc +--source suite/galera_3nodes/include/galera_sr_crash_post_check.inc + + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-810B.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-810B.test new file mode 100644 index 00000000000..24a518af9f7 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-810B.test @@ -0,0 +1,49 @@ +# +# Exercise the crash points which crash the server at various points important to SR +# + +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_debug_sync.inc + +--connect node_2_check, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connect node_3_check, 127.0.0.1, root, , test, $NODE_MYPORT_3 + +# +# crash_apply_cb_before_append_frag +# + +--connection node_3 +SET GLOBAL debug="d,crash_apply_cb_before_append_frag"; +--source suite/galera_3nodes/include/galera_expect_node_crash.inc +--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes2.inc + +--connection node_3 +--error 0,2006,2013 +COMMIT; + +--source include/start_mysqld.inc +--sleep 5 +--source suite/galera_3nodes/include/galera_sr_crash_post_check2.inc + +# +# crash_apply_cb_after_append_frag +# + +--connection node_3 +SET GLOBAL debug="d,crash_apply_cb_after_append_frag"; +--source suite/galera_3nodes/include/galera_expect_node_crash.inc +--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes2.inc + +--connection node_3 +--error 0,2006,2013 +COMMIT; + +--source include/start_mysqld.inc +--sleep 5 +--source suite/galera_3nodes/include/galera_sr_crash_post_check2.inc + +--connection node_1 +CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member"); +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-810C.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-810C.test new file mode 100644 index 00000000000..79948e5a46d --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-810C.test @@ -0,0 +1,70 @@ +# +# Exercise the crash points which crash the server at various points important to SR +# + +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_debug_sync.inc + +--connect node_2_check, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--enable_reconnect +--connect node_3_check, 127.0.0.1, root, , test, $NODE_MYPORT_3 + +# +# crash_commit_cb_last_fragment_commit_success +# + +--connection node_3 +SET GLOBAL debug="d,crash_commit_cb_last_fragment_commit_success"; +--source suite/galera_3nodes/include/galera_expect_node_crash.inc +--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes3.inc + +--source include/start_mysqld.inc +--sleep 5 +--source include/galera_wait_ready.inc +--source suite/galera_3nodes/include/galera_sr_crash_post_check3.inc + +# +# crash_commit_cb_before_last_fragment_commit +# + +--connection node_3 +SET GLOBAL debug="d,crash_commit_cb_before_last_fragment_commit"; +--source suite/galera_3nodes/include/galera_expect_node_crash.inc +--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes3.inc + +--source include/start_mysqld.inc +--sleep 5 +--source include/galera_wait_ready.inc +--source suite/galera_3nodes/include/galera_sr_crash_post_check3.inc + +# +# crash_apply_cb_after_fragment_removal +# + +--connection node_3 +SET GLOBAL debug="d,crash_apply_cb_after_fragment_removal"; +--source suite/galera_3nodes/include/galera_expect_node_crash.inc +--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes3.inc + +--source include/start_mysqld.inc +--sleep 5 +--source include/galera_wait_ready.inc +--source suite/galera_3nodes/include/galera_sr_crash_post_check3.inc + +# +# crash_apply_cb_before_fragment_removal +# + +--connection node_3 +SET GLOBAL debug="d,crash_apply_cb_before_fragment_removal"; +--source suite/galera_3nodes/include/galera_expect_node_crash.inc +--source suite/galera_3nodes/include/galera_sr_crash_prepare_nodes3.inc + +--source include/start_mysqld.inc +--sleep 5 +--source include/galera_wait_ready.inc +--source suite/galera_3nodes/include/galera_sr_crash_post_check3.inc + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-817.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-817.test new file mode 100644 index 00000000000..c585aba78d4 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-817.test @@ -0,0 +1,101 @@ +# +# GCF-817 SR: master removes SR trx in non-primary view +# + +--source include/galera_cluster.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +INSERT INTO t1 VALUES (6); +INSERT INTO t1 VALUES (7); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET SESSION wsrep_sync_wait = 0; +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +--source include/wait_condition.inc + +--connection node_1a +# Force node #1 to go non-primary +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; + +SET SESSION wsrep_on = OFF; +--let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +--source include/wait_condition.inc + +# SR table on master should still contain entries after going non-Prim +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +# SR table on slave should eventually clean up entries when master goes non-Prim +--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR +--source include/wait_condition.inc + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +# Restore node #1 to primary + +--connection node_1a +# +# The following sleep is a workaround for issue GCF-861. +# Normally it's sufficient to make sure that the CC happened +# by checking that wsrep_cluster_size has shrinked, as above. +# However that is not always enough, so we sleep a few seconds. +# See GCF-861 on how to reproduce. +# + +--connection node_1a +--sleep 6 +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; + +--connection node_3 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +--connection node_1a +--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +--source include/wait_condition.inc + +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--source include/galera_wait_ready.inc + +# SR table on master should contain no entries after going back to Prim state +--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR +--source include/wait_condition.inc + +--connection node_2 +# And none on slave +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_1 +--error ER_LOCK_DEADLOCK +COMMIT; + +# SR table is now empty everywhere +--connection node_1a +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_2 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_2 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-832.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-832.test new file mode 100644 index 00000000000..95d40803506 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-832.test @@ -0,0 +1,36 @@ +# +# GCF-832 SR: wsrep_schema.SR table remains populated on all nodes after crash +# followed by immediate recovery +# +--source include/galera_cluster.inc +--source include/have_debug_sync.inc + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 + +--connection node_2 +SET GLOBAL debug="d,crash_last_fragment_commit_after_fragment_removal"; + +--let $_server_id= `SELECT @@server_id` +--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.$_server_id.expect +--exec echo "wait" > $_expect_file_name + +CREATE TABLE t1 (f1 VARCHAR(30)) ENGINE=InnoDB; + +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; + +INSERT INTO t1 VALUES ('primary'),('primary'),('primary'),('primary'),('primary'); +--error 2013 +COMMIT; + +--source include/start_mysqld.inc + +--connection node_1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_2 +--enable_reconnect +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/t/disabled.def b/mysql-test/suite/galera_3nodes_sr/t/disabled.def new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/disabled.def diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_isolate_master.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_isolate_master.test new file mode 100644 index 00000000000..a55109e57e4 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_isolate_master.test @@ -0,0 +1,127 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test the effect of gmcast.isolate on master during an SR transaction +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +SET SESSION wsrep_trx_fragment_size = 1; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR +--source include/wait_condition.inc + +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) > 0 FROM t1; + +# +# Trigger gmcast.isolate=1 . +# The transaction is aborted and we expect the SR tables to be cleaned up +# + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +--source include/galera_wait_ready.inc + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +--source include/galera_wait_ready.inc + +# +# Expect that the transaction is cleaned up entirely across the cluster and in all wsrep_schema.SR tables +# + +--connection node_2 +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +--source include/wait_condition.inc +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +SELECT COUNT(*) = 0 FROM t1; + +--connection node_3 +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +--source include/wait_condition.inc +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +SELECT COUNT(*) = 0 FROM t1; + +# +# Restore cluster +# + +--connection node_1a +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +--connection node_3 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +--connection node_1a +--source include/galera_wait_ready.inc + +# +# Confirm that the previous transaction is gone on Node #1 as well +# + +--connection node_1 +--error ER_LOCK_DEADLOCK +COMMIT; + +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; + +--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +--source include/wait_condition.inc + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +# +# Confirm that the transaction can be retried +# + +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +COMMIT; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +--source include/wait_condition.inc +SELECT COUNT(*) = 5 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_3 +--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +--source include/wait_condition.inc +SELECT COUNT(*) = 5 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_1 +CALL mtr.add_suppression("failed to send SR rollback for"); +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_join_slave.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_join_slave.test new file mode 100644 index 00000000000..ff892aa20a6 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_join_slave.test @@ -0,0 +1,56 @@ +# +# This test kills the slave before a Streaming Replication transaction has started +# and restarts it when the transaction is already in progress. IST should +# bring the slave up to date so that it can receive the complete transaction. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +--connection node_2 +--source include/shutdown_mysqld.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size` +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connection node_2 +--source include/start_mysqld.inc +--sleep 1 + +--source include/wait_until_connected_again.inc +--source include/galera_wait_ready.inc + +--connection node_1 +INSERT INTO t1 VALUES (6); +INSERT INTO t1 VALUES (7); +INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (9); +INSERT INTO t1 VALUES (10); +COMMIT; +SELECT COUNT(*) = 10 FROM t1; + +--connection node_2 +SELECT COUNT(*) = 10 FROM t1; + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3 +--source include/galera_wait_ready.inc +SELECT COUNT(*) = 10 FROM t1; + +--connection node_1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_master.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_master.test new file mode 100644 index 00000000000..50b8ef0302f --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_master.test @@ -0,0 +1,56 @@ +# +# This test kills the master while a Streaming Replication transaction is in progress +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + + +--connection node_2 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1; +--source include/wait_condition.inc + +--connection node_2 +--source include/kill_galera.inc + +--connection node_3 +# We expect that uncommitted values are no longer present + +--let $wait_condition = SELECT COUNT(*) = 0 FROM t1; +--source include/wait_condition.inc + +--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +--source include/wait_condition.inc + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +# and we can insert them again +--error 0 +INSERT INTO t1 VALUES (1); + +--connection node_2 +--source include/start_mysqld.inc +# --sleep 5 +--source include/wait_until_connected_again.inc +--source include/galera_wait_ready.inc +--sleep 1 + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +SELECT COUNT(*) = 1 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply.test new file mode 100644 index 00000000000..7b11dfeddea --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply.test @@ -0,0 +1,75 @@ +# +# This test kills the slave while a Streaming Replication transaction is in progress +# and after a fragment has already been applied on the slave. It is expected that +# after the slave restarts, the cluster will continue to be consistent +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 + +--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size` +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1; +--source include/wait_condition.inc + +--source include/kill_galera.inc +--sleep 1 + +--connection node_1 +INSERT INTO t1 VALUES (6); +INSERT INTO t1 VALUES (7); +INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (9); +INSERT INTO t1 VALUES (10); + +--connection node_2 +--source include/start_mysqld.inc +--sleep 1 + +--source include/wait_until_connected_again.inc +--source include/galera_wait_ready.inc + +--connection node_1 +INSERT INTO t1 VALUES (11); +INSERT INTO t1 VALUES (12); +INSERT INTO t1 VALUES (13); +INSERT INTO t1 VALUES (14); +INSERT INTO t1 VALUES (15); + +--connection node_2 + +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) = 15 FROM t1; +--source include/wait_condition.inc + +SELECT COUNT(*) = 15 FROM wsrep_schema.SR; + +--connection node_1 +COMMIT; + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SELECT COUNT(*) = 15 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +DROP TABLE t1; + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3 +CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member"); diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply_rollback.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply_rollback.test new file mode 100644 index 00000000000..2e62810cef4 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply_rollback.test @@ -0,0 +1,76 @@ +# +# This test kills the slave while a Streaming Replication transaction is in progress +# and after a fragment has already been applied on the slave. It is expected that +# after the slave restarts, the cluster will continue to be consistent even if ROLLBACK +# is issued on the SR transaction after restart. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 + +--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size` +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1; +--source include/wait_condition.inc + +--source include/kill_galera.inc +--sleep 1 + +--connection node_1 +INSERT INTO t1 VALUES (6); +INSERT INTO t1 VALUES (7); +INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (9); +INSERT INTO t1 VALUES (10); + +--connection node_2 +--source include/start_mysqld.inc +--sleep 1 + +--source include/wait_until_connected_again.inc +--source include/galera_wait_ready.inc + +--connection node_1 +INSERT INTO t1 VALUES (11); +INSERT INTO t1 VALUES (12); +INSERT INTO t1 VALUES (13); +INSERT INTO t1 VALUES (14); +INSERT INTO t1 VALUES (15); + +--connection node_2 + +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) = 15 FROM t1; +--source include/wait_condition.inc + +SELECT COUNT(*) = 15 FROM wsrep_schema.SR; + +--connection node_1 +ROLLBACK; + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply_rollback2.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply_rollback2.test new file mode 100644 index 00000000000..603483a419c --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply_rollback2.test @@ -0,0 +1,56 @@ +# +# This test kills the slave while a Streaming Replication transaction is in progress +# and after a fragment has already been applied on the slave. It is expected that +# after the slave restarts, the cluster will continue to be consistent +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 + +--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size` +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1; +--source include/wait_condition.inc + +--source include/kill_galera.inc +--sleep 1 + +--connection node_1 +INSERT INTO t1 VALUES (6); +ROLLBACK; + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_2 +--source include/start_mysqld.inc +--sleep 1 + +--source include/wait_until_connected_again.inc +--source include/galera_wait_ready.inc + +--connection node_2 + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_before_apply.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_before_apply.test new file mode 100644 index 00000000000..267552afb60 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_before_apply.test @@ -0,0 +1,71 @@ +# +# This test kills the slave while a Streaming Replication transaction is in progress +# but before a fragment has already been applied on the slave. It is expected that +# after the slave restarts, the cluster will continue to be consistent. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + + +# Block node #2's applier before table t1's inserts have come into play + +--connection node_2 +SELECT COUNT(*) = 0 FROM t1; + +--connection node_1 +CREATE TABLE t2 (f1 INTEGER); + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +LOCK TABLE t2 WRITE; + +--connection node_1 +INSERT INTO t2 VALUES (1); + +--connection node_2 +SET SESSION wsrep_sync_wait = 0; + +--connection node_1 +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connection node_2 +--source include/kill_galera.inc +--sleep 1 + +--source include/start_mysqld.inc +--sleep 1 + +--source include/wait_until_connected_again.inc +--source include/galera_wait_ready.inc + +# Expect that the SR table will get some entries after the restart +# --let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +# --source include/wait_conditions.inc + +# SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +# SELECT COUNT(*) > 0 FROM t1; + +--connection node_1 +COMMIT; +SELECT COUNT(*) = 5 FROM t1; + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +--let $wait_condition = SELECT COUNT(*) = 5 FROM t1; +--source include/wait_condition.inc + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_1 +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_threeway_split.cnf b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_threeway_split.cnf new file mode 100644 index 00000000000..910d945949a --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_threeway_split.cnf @@ -0,0 +1,5 @@ +!include ../galera_3nodes.cnf + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.weight=3' + diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_sr_threeway_split.test b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_threeway_split.test new file mode 100644 index 00000000000..82d693eb28d --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_threeway_split.test @@ -0,0 +1,169 @@ +# +# Test the case where the cluster splits 3 ways . The master remains in the +# primary component and is able to commit its transaction. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +# +# Begin a separate SR transaction on every node and confirm that each node +# has SR table entries for every transaction +# + +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (10); +INSERT INTO t1 VALUES (11); +INSERT INTO t1 VALUES (12); +INSERT INTO t1 VALUES (13); +INSERT INTO t1 VALUES (14); + +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR +--source include/wait_condition.inc + +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (200); +INSERT INTO t1 VALUES (201); +INSERT INTO t1 VALUES (202); +INSERT INTO t1 VALUES (203); +INSERT INTO t1 VALUES (204); + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3 +--let $wait_condition = SELECT COUNT(DISTINCT node_uuid) = 2 FROM wsrep_schema.SR +--source include/wait_condition.inc + +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (300); +INSERT INTO t1 VALUES (301); +INSERT INTO t1 VALUES (302); +INSERT INTO t1 VALUES (303); +INSERT INTO t1 VALUES (304); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connect node_3a, 127.0.0.1, root, , test, $NODE_MYPORT_3 + +--connection node_1a +--let $wait_condition = SELECT COUNT(DISTINCT node_uuid) = 3 FROM wsrep_schema.SR +--source include/wait_condition.inc + +# +# Isolate nodes #2 and #3 into separate non-primary components +# + +--connection node_2a +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; + +--connection node_3a +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; + +--connection node_1a +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +INSERT INTO t1 VALUES (20); +INSERT INTO t1 VALUES (21); +INSERT INTO t1 VALUES (22); +INSERT INTO t1 VALUES (23); +INSERT INTO t1 VALUES (24); + +# +# Restore cluster +# + +--connection node_2a +--source include/wsrep_wait_disconnect.inc +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +--source include/galera_wait_ready.inc + +--connection node_3a +--source include/wsrep_wait_disconnect.inc +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +--source include/galera_wait_ready.inc + +--connection node_1a +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +--let $node_1_gcomm_uuid = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_gcomm_uuid'` + +--connection node_2a +--source include/wait_condition.inc + +--connection node_3a +--source include/wait_condition.inc + + +# +# Confirm that the rejoined nodes only have node #1's transaction in their SR tables +# + +--connection node_2 +--error ER_LOCK_DEADLOCK +COMMIT; +SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR; +--disable_query_log +--eval SELECT DISTINCT node_uuid = '$node_1_gcomm_uuid' AS wsrep_gcomm_uuid_match FROM wsrep_schema.SR; +--enable_query_log + +--connection node_3 +--error ER_LOCK_DEADLOCK +COMMIT; +SELECT COUNT(DISTINCT node_uuid) = 1 FROM wsrep_schema.SR; +--disable_query_log +--eval SELECT DISTINCT node_uuid = '$node_1_gcomm_uuid' AS wsrep_gcomm_uuid_match FROM wsrep_schema.SR; +--enable_query_log + +# +# Finalize transaction on node #1 +# + +--connection node_1 +INSERT INTO t1 VALUES (30); +INSERT INTO t1 VALUES (31); +INSERT INTO t1 VALUES (32); +INSERT INTO t1 VALUES (33); +INSERT INTO t1 VALUES (34); +COMMIT; + +# +# Confirm that transaction is replicated correctly and SR tables are empty at the end of the test +# + +SELECT COUNT(*) = 15, MIN(f1) = 10, MAX(f1) = 34 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +SET AUTOCOMMIT=ON; + +--connection node_2 +COMMIT; +SELECT COUNT(*) = 15, MIN(f1) = 10, MAX(f1) = 34 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +SET AUTOCOMMIT=ON; + +--connection node_3 +COMMIT; +SELECT COUNT(*) = 15, MIN(f1) = 10, MAX(f1) = 34 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +SET AUTOCOMMIT=ON; + +DROP TABLE t1; + +--connection node_1 +CALL mtr.add_suppression("WSREP: failed to send SR rollback for "); +--connection node_2 +CALL mtr.add_suppression("WSREP: failed to send SR rollback for "); +--connection node_3 +CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
\ No newline at end of file diff --git a/mysql-test/suite/galera_ee/galera_2nodes.cnf b/mysql-test/suite/galera_ee/galera_2nodes.cnf new file mode 100644 index 00000000000..0412b5654dd --- /dev/null +++ b/mysql-test/suite/galera_ee/galera_2nodes.cnf @@ -0,0 +1 @@ +!include ../galera/galera_2nodes.cnf diff --git a/mysql-test/suite/galera_ee/galera_4nodes.cnf b/mysql-test/suite/galera_ee/galera_4nodes.cnf new file mode 100644 index 00000000000..7b37e62c314 --- /dev/null +++ b/mysql-test/suite/galera_ee/galera_4nodes.cnf @@ -0,0 +1 @@ +!include ../galera/galera_4nodes.cnf diff --git a/mysql-test/suite/galera_ee/my.cnf b/mysql-test/suite/galera_ee/my.cnf new file mode 100644 index 00000000000..ca163a540d9 --- /dev/null +++ b/mysql-test/suite/galera_ee/my.cnf @@ -0,0 +1 @@ +!include galera_2nodes.cnf diff --git a/mysql-test/suite/galera_ee/r/GCF-329A.result b/mysql-test/suite/galera_ee/r/GCF-329A.result new file mode 100644 index 00000000000..c429b0b8973 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/GCF-329A.result @@ -0,0 +1,30 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t1; +CALL mtr.add_suppression("This will leave database in inconsistent state since DDL execution cannot be terminated in order"); +CALL mtr.add_suppression("Failed to send NBO-end"); +CALL mtr.add_suppression("Failed to acquire total order isolation"); +CALL mtr.add_suppression("Aborting"); +CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown"); +CALL mtr.add_suppression("Slave SQL: Error 'Got error 7 during COMMIT'"); diff --git a/mysql-test/suite/galera_ee/r/GCF-329B.result b/mysql-test/suite/galera_ee/r/GCF-329B.result new file mode 100644 index 00000000000..2a56bd4964a --- /dev/null +++ b/mysql-test/suite/galera_ee/r/GCF-329B.result @@ -0,0 +1,16 @@ +SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_OSU_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;; +Killing server ... +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='t1'; +COUNT(*) = 2 +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='t1'; +COUNT(*) = 2 +1 +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/r/GCF-360.result b/mysql-test/suite/galera_ee/r/GCF-360.result new file mode 100644 index 00000000000..7dc9ba37c19 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/GCF-360.result @@ -0,0 +1,416 @@ +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +ERROR 42S02: Unknown table 'test.nonexisting_table' +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 4 +1 +CALL mtr.add_suppression("Slave SQL: Error 'Unknown table"); +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 4 +1 +CALL mtr.add_suppression("Slave SQL: Error 'Unknown table"); +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 4 +1 +CALL mtr.add_suppression("Slave SQL: Error 'Unknown table"); +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 4 +1 +CALL mtr.add_suppression("Slave SQL: Error 'Unknown table"); diff --git a/mysql-test/suite/galera_ee/r/GCF-421.result b/mysql-test/suite/galera_ee/r/GCF-421.result new file mode 100644 index 00000000000..78dab709e32 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/GCF-421.result @@ -0,0 +1,14 @@ +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +SET GLOBAL DEBUG = 'd,sync.alter_locked_tables_inplace'; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ALGORITHM=INPLACE, ADD PRIMARY KEY (f1);; +DROP TABLE t1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +DROP TABLE t1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET GLOBAL DEBUG = ''; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t1; +CALL mtr.add_suppression("TO isolation failed for"); +CALL mtr.add_suppression("TO isolation failed for"); diff --git a/mysql-test/suite/galera_ee/r/GCF-546.result b/mysql-test/suite/galera_ee/r/GCF-546.result new file mode 100644 index 00000000000..dde91db8422 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/GCF-546.result @@ -0,0 +1,28 @@ +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +SET GLOBAL DEBUG = 'd,sync.alter_locked_tables'; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1);; +ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET GLOBAL DEBUG = ''; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables'; +ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1); +ERROR 42000: Multiple primary key defined +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +CALL mtr.add_suppression("TO isolation failed"); +CALL mtr.add_suppression("ALTER TABLE isolation failure"); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +CALL mtr.add_suppression("Slave SQL: Error"); +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/r/GCF-563.result b/mysql-test/suite/galera_ee/r/GCF-563.result new file mode 100644 index 00000000000..8de6dfd36e7 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/GCF-563.result @@ -0,0 +1,52 @@ +SET GLOBAL wsrep_slave_threads=2; +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t2 LOCK=SHARED, ADD PRIMARY KEY (f1);; +SET SESSION wsrep_sync_wait=0; +SET GLOBAL debug = ''; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +DROP TABLE t2; +SET GLOBAL wsrep_slave_threads=1; diff --git a/mysql-test/suite/galera_ee/r/GCF-849.result b/mysql-test/suite/galera_ee/r/GCF-849.result new file mode 100644 index 00000000000..599d5451f2a --- /dev/null +++ b/mysql-test/suite/galera_ee/r/GCF-849.result @@ -0,0 +1,11 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` int(11) DEFAULT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/r/GCF-854.result b/mysql-test/suite/galera_ee/r/GCF-854.result new file mode 100644 index 00000000000..0752a169d73 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/GCF-854.result @@ -0,0 +1,16 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER; +INSERT INTO t1 VALUES (2,2); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` int(11) DEFAULT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/r/galera-features#117.result b/mysql-test/suite/galera_ee/r/galera-features#117.result new file mode 100644 index 00000000000..f44269df9f0 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera-features#117.result @@ -0,0 +1,29 @@ +SET GLOBAL wsrep_on=OFF; +CREATE TABLE test.t1 (f2 INTEGER); +SET GLOBAL wsrep_on=ON; +CREATE TABLE test.t1 (f1 INTEGER); +ERROR 42S01: Table 't1' already exists +SET SESSION wsrep_sync_wait=0; +SHOW CREATE TABLE test.t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW STATUS LIKE 'wsrep_cluster_status'; +Variable_name Value +wsrep_cluster_status Primary +DROP TABLE test.t1; +SET SESSION wsrep_sync_wait=0; +SET GLOBAL wsrep_on=OFF; +SHOW CREATE TABLE test.t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f2` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW STATUS LIKE 'wsrep_cluster_status'; +Variable_name Value +wsrep_cluster_status non-Primary +Killing server ... +CALL mtr.add_suppression("Inconsistent by consensus."); +CALL mtr.add_suppression("WSREP: Failed to execute TOI action"); +CALL mtr.add_suppression("WSREP: TO isolation end failed"); diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_conflicting.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_conflicting.result new file mode 100644 index 00000000000..0090878afd8 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_conflicting.result @@ -0,0 +1,14 @@ +SET GLOBAL wsrep_slave_threads=2; +CREATE TABLE t1 (f1 INTEGER NOT NULL, f2 INTEGER NOT NULL) ENGINE=InnoDB; +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f2);; +SET SESSION wsrep_sync_wait=0; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; +CALL mtr.add_suppression("Slave SQL: Error 'Multiple primary key defined' on query"); +SET GLOBAL wsrep_slave_threads = 1; diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_copy.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_copy.result new file mode 100644 index 00000000000..abc6c3f4148 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_copy.result @@ -0,0 +1,44 @@ +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET GLOBAL debug = 'd,sync.alter_locked_tables'; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 ALGORITHM=COPY, LOCK=SHARED, ADD PRIMARY KEY (f1);; +SET SESSION wsrep_sync_wait=0; +INSERT INTO t2 VALUES (2); +SET SESSION lock_wait_timeout=1; +INSERT INTO t1 VALUES (1); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SET SESSION lock_wait_timeout=1; +INSERT INTO t2 VALUES (3); +INSERT INTO t1 VALUES (3); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables'; +SET GLOBAL debug = ''; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 2 FROM t2; +COUNT(*) = 2 +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 2 FROM t2; +COUNT(*) = 2 +1 +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_engine.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_engine.result new file mode 100644 index 00000000000..1f1d58cdd76 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_engine.result @@ -0,0 +1,22 @@ +SET GLOBAL wsrep_replicate_myisam=ON; +CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1); +SET SESSION wsrep_OSU_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ENGINE=InnoDB; +INSERT INTO t1 VALUES (2); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; +SET GLOBAL wsrep_replicate_myisam=FALSE; diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_error_duplicate.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_error_duplicate.result new file mode 100644 index 00000000000..252fe9d6740 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_error_duplicate.result @@ -0,0 +1,30 @@ +CREATE TABLE t1 (f1 INTEGER); +INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(1); +SET SESSION wsrep_OSU_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1); +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +INSERT INTO t1 VALUES (1); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 7 FROM t1; +COUNT(*) = 7 +1 +ALTER IGNORE TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1); +Warnings: +Warning 1681 'IGNORE' is deprecated and will be removed in a future release. +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_exclusive.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_exclusive.result new file mode 100644 index 00000000000..21e6c51374b --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_exclusive.result @@ -0,0 +1,37 @@ +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +SET SESSION wsrep_osu_method=NBO; +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; +ALTER TABLE t1 LOCK=EXCLUSIVE, ADD PRIMARY KEY (f1);; +SET SESSION wsrep_sync_wait=0; +SET SESSION lock_wait_timeout=1; +INSERT INTO t1 VALUES (1); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SELECT * FROM t1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SET SESSION lock_wait_timeout=1; +INSERT INTO t1 VALUES (3); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SELECT * FROM t1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_inplace.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_inplace.result new file mode 100644 index 00000000000..70ef1bc083e --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_inplace.result @@ -0,0 +1,39 @@ +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; +SET SESSION wsrep_osu_method='NBO'; +ALTER TABLE t1 LOCK=SHARED, ALGORITHM=INPLACE, ADD PRIMARY KEY (f1);; +SET SESSION wsrep_sync_wait=0; +INSERT INTO t2 VALUES (2); +ALTER TABLE t2 ALGORITHM=COPY, ADD COLUMN f2 INTEGER; +SET SESSION lock_wait_timeout=1; +INSERT INTO t1 VALUES (1); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SET SESSION lock_wait_timeout=1; +INSERT INTO t2 VALUES (3,4); +INSERT INTO t1 VALUES (3); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +ALTER TABLE t2 ALGORITHM=COPY, ADD COLUMN f3 INTEGER; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_multi.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_multi.result new file mode 100644 index 00000000000..923df0d13cf --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_multi.result @@ -0,0 +1,11 @@ +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1), ADD COLUMN f2 INTEGER; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` int(11) DEFAULT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_nonconflicting.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_nonconflicting.result new file mode 100644 index 00000000000..eb780a6b264 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_nonconflicting.result @@ -0,0 +1,29 @@ +SET GLOBAL wsrep_slave_threads=2; +CREATE TABLE t1 (f1 INTEGER NOT NULL, f2 INTEGER NOT NULL) ENGINE=InnoDB; +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1);; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD KEY (f2);; +SET SESSION wsrep_sync_wait=0; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` int(11) NOT NULL, + PRIMARY KEY (`f1`), + KEY `f2` (`f2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` int(11) NOT NULL, + PRIMARY KEY (`f1`), + KEY `f2` (`f2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SET GLOBAL wsrep_slave_threads = 1; +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_parallel.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_parallel.result new file mode 100644 index 00000000000..6a15c68c393 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_parallel.result @@ -0,0 +1,45 @@ +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +CREATE TABLE t3 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +SET GLOBAL debug = 'd,sync.alter_locked_tables:d,sync.alter_locked_tables_inplace'; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1);; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t2 LOCK=SHARED, ALGORITHM=INPLACE, ADD PRIMARY KEY (f1);; +SET SESSION wsrep_sync_wait=0; +INSERT INTO t3 VALUES (1); +INSERT INTO t3 VALUES (2); +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables'; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 2 FROM t3; +COUNT(*) = 2 +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 2 FROM t3; +COUNT(*) = 2 +1 +DROP TABLE t1, t2, t3; diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_partition.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_partition.result new file mode 100644 index 00000000000..d66cfd5234c --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_partition.result @@ -0,0 +1,26 @@ +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED PARTITION BY HASH(f1) PARTITIONS 8; +INSERT INTO t1 VALUES (1); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +/*!50100 PARTITION BY HASH (f1) +PARTITIONS 8 */ +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +ALTER TABLE t1 LOCK=SHARED REMOVE PARTITIONING; +INSERT INTO t1 VALUES (2); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_rename.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_rename.result new file mode 100644 index 00000000000..22d9dfbc26a --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_rename.result @@ -0,0 +1,19 @@ +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=EXCLUSIVE, RENAME TO t2; +ERROR 42S01: Table 't2' already exists +ALTER TABLE t1 LOCK=EXCLUSIVE, RENAME TO t3; +SHOW CREATE TABLE t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `f1` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 1 FROM t3; +COUNT(*) = 1 +1 +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t2; +DROP TABLE t3; +CALL mtr.add_suppression("Slave SQL: Error 'Table 't2' already exists' on query."); diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_alter_toi.result b/mysql-test/suite/galera_ee/r/galera_nbo_alter_toi.result new file mode 100644 index 00000000000..3ac59facc0f --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_nbo_alter_toi.result @@ -0,0 +1,38 @@ +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);; +ALTER TABLE t2 LOCK=SHARED, ADD COLUMN f2 INTEGER; +SET SESSION wsrep_sync_wait=0; +SET GLOBAL debug = ''; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_create_index.result b/mysql-test/suite/galera_ee/r/galera_nbo_create_index.result new file mode 100644 index 00000000000..4c43149e28d --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_nbo_create_index.result @@ -0,0 +1,36 @@ +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(1); +SET SESSION wsrep_osu_method=NBO; +CREATE INDEX i1 ON t1 (f1); +ERROR 42000: wsrep_OSU_method NBO not supported for query +CREATE UNIQUE INDEX i1 ON t1 (f1) LOCK=SHARED; +ERROR 23000: Duplicate entry '1' for key 'i1' +CREATE INDEX i1 ON t1 (f1) LOCK=SHARED; +INSERT INTO t1 VALUES (2); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + KEY `i1` (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + KEY `i1` (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT COUNT(*) = 3 FROM t1; +COUNT(*) = 3 +1 +DROP INDEX i1 ON t1 LOCK=EXCLUSIVE; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_ddl_error.result b/mysql-test/suite/galera_ee/r/galera_nbo_ddl_error.result new file mode 100644 index 00000000000..8715790653a --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_nbo_ddl_error.result @@ -0,0 +1,22 @@ +CREATE TABLE t1 (f1 INTEGER, f2 INTEGER); +SET SESSION wsrep_OSU_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER; +ERROR 42S21: Duplicate column name 'f2' +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f3 INTEGER; +SET SESSION wsrep_OSU_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f4 INTEGER; +SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 4 +1 +SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 4 +1 +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t1; +CALL mtr.add_suppression("Slave SQL: Error 'Duplicate column name"); diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_error_on_all.result b/mysql-test/suite/galera_ee/r/galera_nbo_error_on_all.result new file mode 100644 index 00000000000..f45f100b73c --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_nbo_error_on_all.result @@ -0,0 +1,13 @@ +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1); +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_local_mdl.result b/mysql-test/suite/galera_ee/r/galera_nbo_local_mdl.result new file mode 100644 index 00000000000..476e35eac95 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_nbo_local_mdl.result @@ -0,0 +1,12 @@ +CREATE TABLE t1 (f1 INTEGER, f2 INTEGER); +CREATE TABLE t2 (f1 INTEGER); +LOCK TABLE t1 WRITE; +SET SESSION wsrep_OSU_method=NBO; +ALTER TABLE t1 LOCK=SHARED, DROP COLUMN f2;; +SET SESSION wsrep_sync_wait = 0; +INSERT INTO t2 VALUES (1);; +SET SESSION wsrep_sync_wait = 0; +INSERT INTO t2 VALUES (1); +CREATE TABLE t3 (t4 INTEGER); +UNLOCK TABLES; +DROP TABLE t1, t2, t3; diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_processlist.result b/mysql-test/suite/galera_ee/r/galera_nbo_processlist.result new file mode 100644 index 00000000000..d17e5c5a777 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_nbo_processlist.result @@ -0,0 +1,35 @@ +SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'; +COUNT(*) = 3 +1 +SET GLOBAL debug = 'd,sync.alter_opened_table'; +SET SESSION wsrep_sync_wait = 0; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_osu_method='NBO'; +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST +WHERE USER = 'system user' +AND STATE = 'debug sync point: now' +AND INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 1 +1 +ERROR HYN: You are not owner of thread N +ERROR HYN: You are not owner of thread N +SET DEBUG_SYNC= 'now SIGNAL signal.alter_opened_table'; +SET SESSION wsrep_sync_wait = 7; +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST +WHERE USER = 'system user' +AND STATE = 'debug sync point: now' +AND INFO = 'ALTER TABLE t1 ADD COLUMN f2 INTEGER'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 +INSERT INTO t1 VALUES (1,2); +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN t3 INTEGER; +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_sst_slave.result b/mysql-test/suite/galera_ee/r/galera_nbo_sst_slave.result new file mode 100644 index 00000000000..76ff10dc4d7 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_nbo_sst_slave.result @@ -0,0 +1,23 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER;; +SET SESSION wsrep_sync_wait = 0; +include/assert_grep.inc [Master should report that it can not donate SST] +include/assert_grep.inc [Slave should report that it could not join] +SET GLOBAL debug = ''; +SET DEBUG_SYNC='now SIGNAL signal.alter_locked_tables_inplace'; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` int(11) DEFAULT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t1; +CALL mtr.add_suppression("Non-blocking operation in progress, cannot donate SST"); +CALL mtr.add_suppression("Resource temporarily unavailable"); +CALL mtr.add_suppression("Resource temporarily unavailable"); +CALL mtr.add_suppression("Will never receive state"); +CALL mtr.add_suppression("terminated unexpectedly"); diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_temporary_table.result b/mysql-test/suite/galera_ee/r/galera_nbo_temporary_table.result new file mode 100644 index 00000000000..17d26ed6b8e --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_nbo_temporary_table.result @@ -0,0 +1,14 @@ +RESET MASTER; +RESET MASTER; +CREATE TEMPORARY TABLE t1 (f1 INTEGER, f2 INTEGER); +SET SESSION wsrep_OSU_method=NBO; +ALTER TABLE t1 LOCK=SHARED, DROP COLUMN f2; +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +COUNT(*) = 0 +1 +SHOW BINLOG EVENTS IN '0.000001' FROM 120; +Log_name Pos Event_type Server_id End_log_pos Info +SHOW BINLOG EVENTS IN '0.000001' FROM 120; +Log_name Pos Event_type Server_id End_log_pos Info +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/r/galera_nbo_unsupported.result b/mysql-test/suite/galera_ee/r/galera_nbo_unsupported.result new file mode 100644 index 00000000000..545e8ad3969 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_nbo_unsupported.result @@ -0,0 +1,26 @@ +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +SET SESSION wsrep_osu_method='NBO'; +CREATE TABLE t2 (f1 INTEGER); +ERROR 42000: wsrep_OSU_method NBO not supported for query +RENAME TABLE t1 TO t2; +ERROR 42000: wsrep_OSU_method NBO not supported for query +ALTER TABLE t1 LOCK=DEFAULT, ADD COLUMN f2 INTEGER; +ERROR 42000: wsrep_OSU_method NBO not supported for query +ALTER TABLE t2 LOCK=NONE, ADD COLUMN f2 INTEGER; +ERROR 42000: wsrep_OSU_method NBO not supported for query +DROP TABLE t1; +ERROR 42000: wsrep_OSU_method NBO not supported for query +REPAIR TABLE t1; +ERROR 42000: wsrep_OSU_method NBO not supported for query +CREATE USER u1 IDENTIFIED BY 'p1'; +ERROR 42000: wsrep_OSU_method NBO not supported for query +DROP USER u1; +ERROR 42000: wsrep_OSU_method NBO not supported for query +SET SESSION wsrep_osu_method=TOI; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CALL mtr.add_suppression('ALTER TABLE isolation failure'); diff --git a/mysql-test/suite/galera_ee/r/galera_vote_rejoin_ddl.result b/mysql-test/suite/galera_ee/r/galera_vote_rejoin_ddl.result new file mode 100644 index 00000000000..361e1f71258 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_vote_rejoin_ddl.result @@ -0,0 +1,44 @@ +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1'; +SET SESSION wsrep_on=OFF; +CREATE TABLE t1 (f1 INTEGER); +SET SESSION wsrep_on=ON; +DROP TABLE t1; +CREATE TABLE t2 (f1 INTEGER); +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0'; +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2'; +COUNT(*) = 1 +1 +SET SESSION wsrep_on=OFF; +Killing server ... +Starting mysqld +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2'; +COUNT(*) = 1 +1 +CALL mtr.add_suppression("Slave SQL: Error 'Unknown table"); +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2'; +COUNT(*) = 1 +1 +CALL mtr.add_suppression("Slave SQL: Error 'Unknown table"); +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2'; +COUNT(*) = 1 +1 +CALL mtr.add_suppression("inconsistent with group"); +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2'; +COUNT(*) = 1 +1 +DROP TABLE t2; diff --git a/mysql-test/suite/galera_ee/r/galera_vote_rejoin_dml.result b/mysql-test/suite/galera_ee/r/galera_vote_rejoin_dml.result new file mode 100644 index 00000000000..e3dd272e1d3 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/galera_vote_rejoin_dml.result @@ -0,0 +1,47 @@ +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1'; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 'A'); +SET SESSION wsrep_on=OFF; +INSERT INTO t1 VALUES (2, 'B'); +SET SESSION wsrep_on=ON; +DELETE FROM t1 WHERE f1 = 2; +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0'; +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B'; +COUNT(*) = 0 +1 +SET SESSION wsrep_on=OFF; +Killing server ... +Starting mysqld +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B'; +COUNT(*) = 0 +1 +CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows"); +CALL mtr.add_suppression("Delete_rows apply failed"); +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B'; +COUNT(*) = 0 +1 +CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows"); +CALL mtr.add_suppression("Delete_rows apply failed"); +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B'; +COUNT(*) = 0 +1 +CALL mtr.add_suppression("inconsistent with group"); +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B'; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/r/mysql-wsrep-features#127.result b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#127.result new file mode 100644 index 00000000000..089d0303750 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#127.result @@ -0,0 +1,5 @@ +CREATE TABLE t1 (f1 INTEGER); +SET GLOBAL wsrep_OSU_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER; +SET GLOBAL wsrep_OSU_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/r/mysql-wsrep-features#128.result b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#128.result new file mode 100644 index 00000000000..b513ef9d560 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#128.result @@ -0,0 +1,7 @@ +SET SESSION wsrep_OSU_method=TOI; +CREATE TABLE t1 (f1 INTEGER); +SET SESSION wsrep_OSU_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER; +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; +SET SESSION wsrep_OSU_method=NBO; diff --git a/mysql-test/suite/galera_ee/r/mysql-wsrep-features#131.result b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#131.result new file mode 100644 index 00000000000..3a6ad0f620f --- /dev/null +++ b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#131.result @@ -0,0 +1,12 @@ +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET SESSION wsrep_osu_method=NBO; +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; +ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1);; +SET SESSION wsrep_sync_wait=0; +INSERT INTO t1 VALUES (1);; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/r/mysql-wsrep-features#132.result b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#132.result new file mode 100644 index 00000000000..50e5f97fdb7 --- /dev/null +++ b/mysql-test/suite/galera_ee/r/mysql-wsrep-features#132.result @@ -0,0 +1,18 @@ +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET SESSION wsrep_osu_method=NBO; +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; +ALTER TABLE t1 ADD PRIMARY KEY (f1), ALGORITHM=INPLACE, LOCK=SHARED;; +SET SESSION wsrep_sync_wait=0; +INSERT INTO t2 VALUES (1); +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; +SELECT COUNT(*) = 1 FROM t2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t2; +COUNT(*) = 1 +1 +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera_ee/t/GCF-329A.test b/mysql-test/suite/galera_ee/t/GCF-329A.test new file mode 100644 index 00000000000..284aa971b44 --- /dev/null +++ b/mysql-test/suite/galera_ee/t/GCF-329A.test @@ -0,0 +1,42 @@ +# +# GCF-329: NB-DDL: "no corresponding NBO begin found for NBO end" when restarting slave +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/big_test.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +SET SESSION wsrep_osu_method=NBO; +--send ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1); + +--connection node_2 +--source include/restart_mysqld.inc + +--let $galera_connection_name = node_2a +--let $galera_server_number = 2 +--source include/galera_connect.inc +--connection node_2a +--source include/galera_wait_ready.inc + +SELECT COUNT(*) = 1 FROM t1; +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +SHOW CREATE TABLE t1; + +--connection node_1 +--reap +SHOW CREATE TABLE t1; + +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t1; + +--connection node_2 +CALL mtr.add_suppression("This will leave database in inconsistent state since DDL execution cannot be terminated in order"); +CALL mtr.add_suppression("Failed to send NBO-end"); +CALL mtr.add_suppression("Failed to acquire total order isolation"); +CALL mtr.add_suppression("Aborting"); +CALL mtr.add_suppression("Plugin 'InnoDB' will be forced to shutdown"); +CALL mtr.add_suppression("Slave SQL: Error 'Got error 7 during COMMIT'"); diff --git a/mysql-test/suite/galera_ee/t/GCF-329B.test b/mysql-test/suite/galera_ee/t/GCF-329B.test new file mode 100644 index 00000000000..248301280cc --- /dev/null +++ b/mysql-test/suite/galera_ee/t/GCF-329B.test @@ -0,0 +1,53 @@ +# +# GCF-329 NB-DDL: "no corresponding NBO begin found for NBO end" when restarting slave +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/big_test.inc + +--connection node_1 + +# Enable the master to continue running during the split-brain situation that +# occurs when the slave is killed +--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options` +SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; + +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +--connection node_1 +SET SESSION wsrep_OSU_method=NBO; +--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER; + +--connection node_2 +--source include/kill_galera.inc + +--let $galera_connection_name = node_1a +--let $galera_server_number = 1 +--source include/galera_connect.inc +--connection node_1a +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_2 +--source include/start_mysqld.inc + +--let $galera_connection_name = node_2a +--let $galera_server_number = 2 +--source include/galera_connect.inc +--connection node_2a + +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='t1'; +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + +--connection node_1 +--reap + +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='t1'; +SET SESSION wsrep_OSU_method=TOI; + +--disable_query_log +--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_orig'; +--enable_query_log + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/t/GCF-360.cnf b/mysql-test/suite/galera_ee/t/GCF-360.cnf new file mode 100644 index 00000000000..28e51f87e8e --- /dev/null +++ b/mysql-test/suite/galera_ee/t/GCF-360.cnf @@ -0,0 +1,17 @@ +!include ../galera_4nodes.cnf + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port' +wsrep_ignore_apply_errors=0 + +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port' +wsrep_ignore_apply_errors=0 + +[mysqld.3] +wsrep_provider_options='base_port=@mysqld.3.#galera_port' +wsrep_ignore_apply_errors=0 + +[mysqld.4] +wsrep_provider_options='base_port=@mysqld.4.#galera_port' +wsrep_ignore_apply_errors=0 diff --git a/mysql-test/suite/galera_ee/t/GCF-360.test b/mysql-test/suite/galera_ee/t/GCF-360.test new file mode 100644 index 00000000000..e2684135810 --- /dev/null +++ b/mysql-test/suite/galera_ee/t/GCF-360.test @@ -0,0 +1,64 @@ +# +# GCF-360 Inconsistency voting: node goes non-prim on DDL that fails everywhere +# +# We issue 400 DDLs in total to make this test more stressful# +# + +--source include/galera_cluster.inc + +--let $count = 100 + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4 + +--disable_query_log +while ($count) +{ + --connection node_1 + --send DROP TABLE nonexisting_table; + + --connection node_2 + --send DROP TABLE nonexisting_table; + + --connection node_3 + --send DROP TABLE nonexisting_table; + + --connection node_4 + --send DROP TABLE nonexisting_table; + + --connection node_1 + --error ER_BAD_TABLE_ERROR + --reap + + --connection node_2 + --error ER_BAD_TABLE_ERROR + --reap + + --connection node_3 + --error ER_BAD_TABLE_ERROR + --reap + + --connection node_4 + --error ER_BAD_TABLE_ERROR + --reap + + --dec $count +} + +--enable_query_log + +--connection node_1 +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +CALL mtr.add_suppression("Slave SQL: Error 'Unknown table"); + +--connection node_2 +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +CALL mtr.add_suppression("Slave SQL: Error 'Unknown table"); + +--connection node_3 +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +CALL mtr.add_suppression("Slave SQL: Error 'Unknown table"); + +--connection node_4 +SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +CALL mtr.add_suppression("Slave SQL: Error 'Unknown table"); diff --git a/mysql-test/suite/galera_ee/t/GCF-421.test b/mysql-test/suite/galera_ee/t/GCF-421.test new file mode 100644 index 00000000000..2fca972e88f --- /dev/null +++ b/mysql-test/suite/galera_ee/t/GCF-421.test @@ -0,0 +1,46 @@ +# +# GCF-421 NB-DDL: Applier thread fails with concurrent DDL +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; + +--connection node_2 +SET GLOBAL DEBUG = 'd,sync.alter_locked_tables_inplace'; + +--connection node_1 +SET SESSION wsrep_osu_method=NBO; +--send ALTER TABLE t1 LOCK=SHARED, ALGORITHM=INPLACE, ADD PRIMARY KEY (f1); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a + +--let $wait_condition = SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE '%ALTER%' +--source include/wait_condition.inc + +--error ER_LOCK_DEADLOCK +DROP TABLE t1; + +--connection node_2 +--error ER_LOCK_DEADLOCK +DROP TABLE t1; + +SET GLOBAL DEBUG = ''; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; + +--connection node_1 +--reap + +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t1; + +CALL mtr.add_suppression("TO isolation failed for"); + +--connection node_2 +CALL mtr.add_suppression("TO isolation failed for"); + + diff --git a/mysql-test/suite/galera_ee/t/GCF-546.test b/mysql-test/suite/galera_ee/t/GCF-546.test new file mode 100644 index 00000000000..5c3e0aacc8a --- /dev/null +++ b/mysql-test/suite/galera_ee/t/GCF-546.test @@ -0,0 +1,47 @@ +# +# GCF-546 NB-DDL: Assertion `thd->wsrep_trx_meta.gtid.seqno == (-1)' failed in wsrep_to_isolation_begin with conflicting DDL on same table +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; + +--connection node_2 +SET GLOBAL DEBUG = 'd,sync.alter_locked_tables'; +SET SESSION wsrep_sync_wait = 0; + +--connection node_1 +SET SESSION wsrep_osu_method=NBO; +--send ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%'; +--source include/wait_condition.inc + +--error ER_LOCK_DEADLOCK +ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1); + +SET GLOBAL DEBUG = ''; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables'; + +--connection node_1 +--reap + +--connection node_2 +--error ER_MULTIPLE_PRI_KEY +ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1); + +SHOW CREATE TABLE t1; + +CALL mtr.add_suppression("TO isolation failed"); +CALL mtr.add_suppression("ALTER TABLE isolation failure"); + +--connection node_1 +SHOW CREATE TABLE t1; +CALL mtr.add_suppression("Slave SQL: Error"); + +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/t/GCF-563.test b/mysql-test/suite/galera_ee/t/GCF-563.test new file mode 100644 index 00000000000..91a92ce2766 --- /dev/null +++ b/mysql-test/suite/galera_ee/t/GCF-563.test @@ -0,0 +1,63 @@ +# +# GCF-563 NB-DDL: Assertion `kep->ref_trx(ke.key().prefix()) == ts' failed in do_clean_nbo with two independent DDLs running at the same time +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + +--connection node_2 +SET GLOBAL wsrep_slave_threads=2; + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB; + +--connection node_2 +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; + +--connection node_1 +SET SESSION wsrep_osu_method=NBO; +--send ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +SET SESSION wsrep_osu_method=NBO; +--send ALTER TABLE t2 LOCK=SHARED, ADD PRIMARY KEY (f1); + +--connection node_2 +SET SESSION wsrep_sync_wait=0; + +# Wait for the ALTER to block in sync point +--let $wait_condition = SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now'; +--source include/wait_condition.inc + +SET GLOBAL debug = ''; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; + +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%'; +--source include/wait_condition.inc + +--connection node_1 +--reap + +--connection node_1a +--reap + +--connection node_1 +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; + +--connection node_2 +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; + +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; + +DROP TABLE t1; +DROP TABLE t2; + +SET GLOBAL wsrep_slave_threads=1; diff --git a/mysql-test/suite/galera_ee/t/GCF-849.test b/mysql-test/suite/galera_ee/t/GCF-849.test new file mode 100644 index 00000000000..20389cfea64 --- /dev/null +++ b/mysql-test/suite/galera_ee/t/GCF-849.test @@ -0,0 +1,39 @@ +# +# GCF-849 NB-DDL: Assertion `last_seen_seqno_ < global_seqno_' failed in galera::TrxHandleSlave::unserialize during IST +# + +--source include/galera_cluster.inc +--source include/big_test.inc + +# Shut down node #2 and wait until it is completely gone +--connection node_2 +--source include/shutdown_mysqld.inc +--sleep 2 + +--connection node_1 +--source include/wait_until_connected_again.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +# Perform an ALTER under NBO + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER; + +# Restart node #2 so that IST happens + +--connection node_2 +--source include/start_mysqld.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +--connection node_2 +--source include/wait_until_connected_again.inc + +SHOW CREATE TABLE t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/t/GCF-854.test b/mysql-test/suite/galera_ee/t/GCF-854.test new file mode 100644 index 00000000000..0f09720457d --- /dev/null +++ b/mysql-test/suite/galera_ee/t/GCF-854.test @@ -0,0 +1,42 @@ +# +# GCF-854 NB-DDL: Assertion `0' failed in Table_cache_manager::free_table with IST +# + +--source include/galera_cluster.inc +--source include/big_test.inc + +# Shut down node #2 and wait until it is completely gone +--connection node_2 +--source include/shutdown_mysqld.inc +--sleep 2 + +--connection node_1 +--source include/wait_until_connected_again.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +# Perform an ALTER under NBO + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER; +INSERT INTO t1 VALUES (2,2); + +# Restart node #2 so that IST happens + +--connection node_2 +--source include/start_mysqld.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +--connection node_2 +--source include/wait_until_connected_again.inc + +SHOW CREATE TABLE t1; +SELECT COUNT(*) = 2 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/t/galera-features#117.cnf b/mysql-test/suite/galera_ee/t/galera-features#117.cnf new file mode 100644 index 00000000000..e20ed7fc08a --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera-features#117.cnf @@ -0,0 +1,4 @@ +!include ../galera_2nodes.cnf + +[mysqld] +wsrep-ignore-apply-errors=0 diff --git a/mysql-test/suite/galera_ee/t/galera-features#117.test b/mysql-test/suite/galera_ee/t/galera-features#117.test new file mode 100644 index 00000000000..fa4af22a385 --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera-features#117.test @@ -0,0 +1,37 @@ +# +# This test tests voting for DDLs (TOI events) +# +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_2 +SET GLOBAL wsrep_on=OFF; +CREATE TABLE test.t1 (f2 INTEGER); +SET GLOBAL wsrep_on=ON; + +--error ER_TABLE_EXISTS_ERROR +CREATE TABLE test.t1 (f1 INTEGER); + +--connection node_1 +# wait for node_2 to disappear +SET SESSION wsrep_sync_wait=0; +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc +SHOW CREATE TABLE test.t1; +SHOW STATUS LIKE 'wsrep_cluster_status'; +DROP TABLE test.t1; + +--connection node_2 +SET SESSION wsrep_sync_wait=0; +--let $wait_condition = SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc +SET GLOBAL wsrep_on=OFF; +SHOW CREATE TABLE test.t1; +SHOW STATUS LIKE 'wsrep_cluster_status'; +--source include/kill_galera.inc +--sleep 1 +--source include/start_mysqld.inc + +CALL mtr.add_suppression("Inconsistent by consensus."); +CALL mtr.add_suppression("WSREP: Failed to execute TOI action"); +CALL mtr.add_suppression("WSREP: TO isolation end failed"); diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_conflicting.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_conflicting.test new file mode 100644 index 00000000000..adcb0fee2cc --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_conflicting.test @@ -0,0 +1,57 @@ +# +# Test that wsrep can process two ALTERs on the same table that are conflicting +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + +--connection node_2 +SET GLOBAL wsrep_slave_threads=2; + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER NOT NULL, f2 INTEGER NOT NULL) ENGINE=InnoDB; + +--connection node_2 +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; + +--connection node_1 +SET SESSION wsrep_osu_method=NBO; +--send ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +SET SESSION wsrep_osu_method=NBO; +--send ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f2); + +--connection node_2 +SET SESSION wsrep_sync_wait=0; + +# Wait for the ALTER to block in sync point +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now'; +--source include/wait_condition.inc + +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; + +--sleep 1 + +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%'; +--source include/wait_condition.inc + +--connection node_1 +--error 0,ER_MULTIPLE_PRI_KEY +--reap + +--connection node_1a +--error 0,ER_MULTIPLE_PRI_KEY +--reap + +SET SESSION wsrep_OSU_method=TOI; + +DROP TABLE t1; + +--connection node_2 +CALL mtr.add_suppression("Slave SQL: Error 'Multiple primary key defined' on query"); + +SET GLOBAL wsrep_slave_threads = 1; diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_copy.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_copy.test new file mode 100644 index 00000000000..fbb7e7e606b --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_copy.test @@ -0,0 +1,67 @@ +# +# Test that ALTER ALGORITHM = COPY works with NBO +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + + +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +--connection node_2 +SET GLOBAL debug = 'd,sync.alter_locked_tables'; + +--connection node_1 +SET SESSION wsrep_osu_method=NBO; + +--send ALTER TABLE t1 ALGORITHM=COPY, LOCK=SHARED, ADD PRIMARY KEY (f1); + +--connection node_2 +SET SESSION wsrep_sync_wait=0; + +# Wait for the ALTER to block in sync point +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now'; +--source include/wait_condition.inc + +# Confirm that unrelated tables can be modified +INSERT INTO t2 VALUES (2); + +# Confirm that the ALTER-ed table can not be modified on either node +SET SESSION lock_wait_timeout=1; +--error ER_LOCK_WAIT_TIMEOUT +INSERT INTO t1 VALUES (1); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +SET SESSION lock_wait_timeout=1; +INSERT INTO t2 VALUES (3); + +--error ER_LOCK_WAIT_TIMEOUT +INSERT INTO t1 VALUES (3); + +# Unblock the ALTER and confirm that it executed on all nodes +--connection node_2 +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables'; +SET GLOBAL debug = ''; + +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%'; +--source include/wait_condition.inc + +SHOW CREATE TABLE t1; +SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) = 2 FROM t2; + +--connection node_1 +--reap + +SHOW CREATE TABLE t1; +SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) = 2 FROM t2; + +SET SESSION wsrep_OSU_method=TOI; + +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_engine.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_engine.test new file mode 100644 index 00000000000..ef463c96543 --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_engine.test @@ -0,0 +1,31 @@ +# +# Test NBO and ALTER ENGINE +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +SET GLOBAL wsrep_replicate_myisam=ON; + +CREATE TABLE t1 (f1 INTEGER) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1); + +SET SESSION wsrep_OSU_method=NBO; + +ALTER TABLE t1 LOCK=SHARED, ENGINE=InnoDB; +INSERT INTO t1 VALUES (2); + +SHOW CREATE TABLE t1; + +--connection node_2 +SHOW CREATE TABLE t1; +SELECT COUNT(*) = 2 FROM t1; + +SET SESSION wsrep_OSU_method=TOI; + +DROP TABLE t1; + +--connection node_1 +SET GLOBAL wsrep_replicate_myisam=FALSE; + diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_error_duplicate.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_error_duplicate.test new file mode 100644 index 00000000000..5a65791db1f --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_error_duplicate.test @@ -0,0 +1,34 @@ +# +# Test NBO and a duplicate key error +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INTEGER); +INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(1); + +--connection node_1 +SET SESSION wsrep_OSU_method=NBO; + +--error ER_DUP_ENTRY +ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1); + +INSERT INTO t1 VALUES (1); + +SHOW CREATE TABLE t1; + +--connection node_2 +SHOW CREATE TABLE t1; +SELECT COUNT(*) = 7 FROM t1; + +--connection node_1 +ALTER IGNORE TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1); + +SELECT COUNT(*) = 5 FROM t1; + +--connection node_1 +SELECT COUNT(*) = 5 FROM t1; + +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_exclusive.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_exclusive.test new file mode 100644 index 00000000000..dafd8f22dbd --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_exclusive.test @@ -0,0 +1,64 @@ +# +# Test that ALTER LOCK=EXCLUSIVE works with NBO +# All DML and SELECTs are expected to be blocked. +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + + +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +SET SESSION wsrep_osu_method=NBO; + +--connection node_2 +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; + +--connection node_1 +--send ALTER TABLE t1 LOCK=EXCLUSIVE, ADD PRIMARY KEY (f1); + +--connection node_2 +SET SESSION wsrep_sync_wait=0; + +# Wait for the ALTER to block in sync point +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now'; +--source include/wait_condition.inc + +# Confirm that the ALTER-ed table can not be modified on either node +SET SESSION lock_wait_timeout=1; + +--error ER_LOCK_WAIT_TIMEOUT +INSERT INTO t1 VALUES (1); + +--error ER_LOCK_WAIT_TIMEOUT +SELECT * FROM t1; + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +SET SESSION lock_wait_timeout=1; + +--error ER_LOCK_WAIT_TIMEOUT +INSERT INTO t1 VALUES (3); + +--error ER_LOCK_WAIT_TIMEOUT +SELECT * FROM t1; + +# Unblock the ALTER and confirm that it executed on all nodes +--connection node_2 +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; + +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%'; +--source include/wait_condition.inc + +SHOW CREATE TABLE t1; +SELECT COUNT(*) = 0 FROM t1; + +--connection node_1 +--reap + +SHOW CREATE TABLE t1; +SELECT COUNT(*) = 0 FROM t1; + +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_inplace.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_inplace.test new file mode 100644 index 00000000000..f0dd0c14937 --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_inplace.test @@ -0,0 +1,67 @@ +# +# Test that ALTER ALGORITHM = INPLACE works with NBO +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +--connection node_2 +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; + +--connection node_1 +SET SESSION wsrep_osu_method='NBO'; +--send ALTER TABLE t1 LOCK=SHARED, ALGORITHM=INPLACE, ADD PRIMARY KEY (f1); + +--connection node_2 +SET SESSION wsrep_sync_wait=0; + +# Wait for the ALTER to block in sync point +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now'; +--source include/wait_condition.inc + +# Confirm that unrelated tables can be modified +INSERT INTO t2 VALUES (2); + +ALTER TABLE t2 ALGORITHM=COPY, ADD COLUMN f2 INTEGER; + +# Confirm that the ALTER-ed table can not be modified on either node +SET SESSION lock_wait_timeout=1; +--error ER_LOCK_WAIT_TIMEOUT +INSERT INTO t1 VALUES (1); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +SET SESSION lock_wait_timeout=1; +INSERT INTO t2 VALUES (3,4); + +--error ER_LOCK_WAIT_TIMEOUT +INSERT INTO t1 VALUES (3); + +ALTER TABLE t2 ALGORITHM=COPY, ADD COLUMN f3 INTEGER; + +# Unblock the ALTER and confirm that it executed on all nodes +--connection node_2 +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; + +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 't1' +--source include/wait_condition.inc + +SHOW CREATE TABLE t1; +SELECT COUNT(*) = 1 FROM t1; + +--connection node_1 +--reap + +SHOW CREATE TABLE t1; +SELECT COUNT(*) = 1 FROM t1; + +--connection node_2 + +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_multi.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_multi.test new file mode 100644 index 00000000000..417ef75e9bb --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_multi.test @@ -0,0 +1,15 @@ +# +# Test multi-item ALTER TABLE under NBO +# + +--source include/galera_cluster.inc + +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; + +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1), ADD COLUMN f2 INTEGER; + +--connection node_2 +SHOW CREATE TABLE t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_nonconflicting.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_nonconflicting.test new file mode 100644 index 00000000000..a0975649182 --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_nonconflicting.test @@ -0,0 +1,57 @@ +# +# Test that wsrep can process two ALTERs on the same table that are not conflicting +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + +--connection node_2 +SET GLOBAL wsrep_slave_threads=2; + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER NOT NULL, f2 INTEGER NOT NULL) ENGINE=InnoDB; + +--connection node_2 +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; + +--connection node_1 +SET SESSION wsrep_osu_method=NBO; +--send ALTER TABLE t1 LOCK=SHARED, ADD PRIMARY KEY (f1); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +SET SESSION wsrep_osu_method=NBO; +--send ALTER TABLE t1 LOCK=SHARED, ADD KEY (f2); + +--connection node_2 +SET SESSION wsrep_sync_wait=0; + +# Wait for the ALTER to block in sync point +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now'; +--source include/wait_condition.inc + +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; + +--sleep 1 + +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%'; +--source include/wait_condition.inc + +--connection node_1 +--reap + +--connection node_1a +--reap + +--connection node_1 +SHOW CREATE TABLE t1; + +--connection node_2 +SHOW CREATE TABLE t1; + +SET GLOBAL wsrep_slave_threads = 1; + +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_parallel.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_parallel.test new file mode 100644 index 00000000000..4799e7b997e --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_parallel.test @@ -0,0 +1,65 @@ +# +# Test that wsrep parallel apply can run two unrelated DDLs at the same time +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +CREATE TABLE t3 (f1 INTEGER NOT NULL) ENGINE=InnoDB; + +--connection node_2 +SET GLOBAL debug = 'd,sync.alter_locked_tables:d,sync.alter_locked_tables_inplace'; + +--connection node_1 +SET SESSION wsrep_osu_method=NBO; +--send ALTER TABLE t1 LOCK=SHARED, ALGORITHM=COPY, ADD PRIMARY KEY (f1); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +SET SESSION wsrep_osu_method=NBO; +--send ALTER TABLE t2 LOCK=SHARED, ALGORITHM=INPLACE, ADD PRIMARY KEY (f1); + +--connection node_2 +SET SESSION wsrep_sync_wait=0; + +# Wait for the ALTERs to block in sync point +--let $wait_condition = SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now'; +--source include/wait_condition.inc + +# Check that the processing of unrelated events is not affected +--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1b +INSERT INTO t3 VALUES (1); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM t3; +INSERT INTO t3 VALUES (2); + +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables'; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; + +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%'; +--source include/wait_condition.inc + +--connection node_1 +--reap + +--connection node_1a +--reap + +--connection node_1 +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; +SELECT COUNT(*) = 2 FROM t3; + +--connection node_2 +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; +SELECT COUNT(*) = 2 FROM t3; + +DROP TABLE t1, t2, t3; diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_partition.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_partition.test new file mode 100644 index 00000000000..46e65038a8c --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_partition.test @@ -0,0 +1,29 @@ +# +# Test that ALTER TABLE works with NBO and partitions +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; + +SET SESSION wsrep_osu_method=NBO; +ALTER TABLE t1 LOCK=SHARED PARTITION BY HASH(f1) PARTITIONS 8; +INSERT INTO t1 VALUES (1); + +--connection node_2 +SHOW CREATE TABLE t1; +SELECT COUNT(*) = 1 FROM t1; + +--connection node_1 +ALTER TABLE t1 LOCK=SHARED REMOVE PARTITIONING; +INSERT INTO t1 VALUES (2); + +--connection node_2 +SHOW CREATE TABLE t1; +SELECT COUNT(*) = 2 FROM t1; + +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_rename.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_rename.test new file mode 100644 index 00000000000..a4892dc085b --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_rename.test @@ -0,0 +1,31 @@ +# +# Test ALTER TABLE RENAME TO with NBO +# All DML and SELECTs are expected to be blocked. +# + +--source include/galera_cluster.inc + +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB; + +SET SESSION wsrep_osu_method=NBO; + +--error ER_TABLE_EXISTS_ERROR +ALTER TABLE t1 LOCK=EXCLUSIVE, RENAME TO t2; + +ALTER TABLE t1 LOCK=EXCLUSIVE, RENAME TO t3; + +--connection node_2 +SHOW CREATE TABLE t3; +SELECT COUNT(*) = 1 FROM t3; + + +SET SESSION wsrep_osu_method=TOI; + +DROP TABLE t2; +DROP TABLE t3; + +CALL mtr.add_suppression("Slave SQL: Error 'Table 't2' already exists' on query."); + diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_alter_toi.test b/mysql-test/suite/galera_ee/t/galera_nbo_alter_toi.test new file mode 100644 index 00000000000..2858f3b51f7 --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_nbo_alter_toi.test @@ -0,0 +1,53 @@ +# +# Test that NBO TOI can coexist with a concurrent, non-conflicting TOI DDL +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +--connection node_2 +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; + +--connection node_1 +SET SESSION wsrep_osu_method=NBO; +--send ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +ALTER TABLE t2 LOCK=SHARED, ADD COLUMN f2 INTEGER; + +--connection node_2 +SET SESSION wsrep_sync_wait=0; + +# Wait for the ALTERs to block in sync point +--let $wait_condition = SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now'; +--source include/wait_condition.inc + +SET GLOBAL debug = ''; +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +--let $wait_condition = SELECT COUNT(*) < 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now'; +--source include/wait_condition.inc + +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO LIKE 'ALTER%'; +--source include/wait_condition.inc + +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; + +--connection node_1 +--reap + +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; + +SET SESSION wsrep_osu_method=TOI; + +DROP TABLE t1; +DROP TABLE t2; + diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_create_index.test b/mysql-test/suite/galera_ee/t/galera_nbo_create_index.test new file mode 100644 index 00000000000..665ab5137a6 --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_nbo_create_index.test @@ -0,0 +1,34 @@ +# +# GCF-852 Allow CREATE/DROP INDEX in NBO mode +# + +--source include/galera_cluster.inc + +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(1); + +SET SESSION wsrep_osu_method=NBO; + +--error ER_NOT_SUPPORTED_YET +CREATE INDEX i1 ON t1 (f1); + +--error ER_DUP_ENTRY +CREATE UNIQUE INDEX i1 ON t1 (f1) LOCK=SHARED; + +--error 0 +CREATE INDEX i1 ON t1 (f1) LOCK=SHARED; +INSERT INTO t1 VALUES (2); +SHOW CREATE TABLE t1; + +--connection node_2 +SHOW CREATE TABLE t1; +SELECT COUNT(*) = 3 FROM t1; + +--connection node_1 +DROP INDEX i1 ON t1 LOCK=EXCLUSIVE; +SHOW CREATE TABLE t1; + +--connection node_2 +SHOW CREATE TABLE t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_ddl_error.test b/mysql-test/suite/galera_ee/t/galera_nbo_ddl_error.test new file mode 100644 index 00000000000..614c133418a --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_nbo_ddl_error.test @@ -0,0 +1,38 @@ +# +# Test that DDL errors are handled correctly under NBO +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INTEGER, f2 INTEGER); + +SET SESSION wsrep_OSU_method=NBO; + +--error ER_DUP_FIELDNAME +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER; + +--connection node_1 +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; + +--connection node_2 +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; + +--connection node_1 +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f3 INTEGER; + +--connection node_2 +SET SESSION wsrep_OSU_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f4 INTEGER; + +--connection node_1 +SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; + +--connection node_2 +SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; + +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t1; + +--connection node_2 +CALL mtr.add_suppression("Slave SQL: Error 'Duplicate column name"); diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_error_on_all.test b/mysql-test/suite/galera_ee/t/galera_nbo_error_on_all.test new file mode 100644 index 00000000000..71205648c8c --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_nbo_error_on_all.test @@ -0,0 +1,21 @@ +# +# Test the case where the DDL produces an error on all nodes +# + +--source include/galera_cluster.inc + +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); + +--connection node_2 +SET SESSION wsrep_osu_method=NBO; + +--error ER_DUP_ENTRY +ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1); + +--connection node_1 +SHOW CREATE TABLE t1; + +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_local_mdl.test b/mysql-test/suite/galera_ee/t/galera_nbo_local_mdl.test new file mode 100644 index 00000000000..dc4fc8e3e35 --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_nbo_local_mdl.test @@ -0,0 +1,55 @@ +# +# Test that if a local MDL lock prevents a particular NBO DDL from completing then: +# * all operations on the local node are blocked +# * all operations on remote node are allowed +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER, f2 INTEGER); +CREATE TABLE t2 (f1 INTEGER); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +LOCK TABLE t1 WRITE; + +--connection node_1 +SET SESSION wsrep_OSU_method=NBO; +--send ALTER TABLE t1 LOCK=SHARED, DROP COLUMN f2; + + +# Confirm that the ALTER is blocked +--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1b +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'Waiting for table metadata lock' +--source include/wait_condition.inc + +# Local DML blocks +--send INSERT INTO t2 VALUES (1); + +# Confirm that the INSERT is blocked +--connect node_1c, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1c +SET SESSION wsrep_sync_wait = 0; + +--let $wait_condition = SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'INSERT INTO t2 VALUES (1)' AND STATE = 'query end' +--source include/wait_condition.inc + +# Remote operations are allowed +--connection node_2 +INSERT INTO t2 VALUES (1); +CREATE TABLE t3 (t4 INTEGER); + +--connection node_1a +UNLOCK TABLES; + +--connection node_1 +--reap + +--connection node_1b +--reap + +DROP TABLE t1, t2, t3; diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_processlist.test b/mysql-test/suite/galera_ee/t/galera_nbo_processlist.test new file mode 100644 index 00000000000..e5c5885c8df --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_nbo_processlist.test @@ -0,0 +1,81 @@ +# +# Check that non-blocking DDL indeed runs in a separate thread as seen in SHOW PROCESSLIST +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc + +--connection node_2 +# At the start, we only have 2 applier threads, 1 standard applier and +# 1 aborter and 1 post aborter +SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'; + +# Set ALTER TABLE to block in the applier thread. wsrep_sync_wait = 0 for the duration, as causal reads will be blocked +--let $debug_orig = `SELECT @@debug` +SET GLOBAL debug = 'd,sync.alter_opened_table'; +SET SESSION wsrep_sync_wait = 0; + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; + +SET SESSION wsrep_osu_method='NBO'; +--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER; + +--connection node_2 +# There is a separate applier thread for the ALTER TABLE +--let $wait_condition = SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'; +--source include/wait_condition.inc + +# The applier thread is blocked +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST +WHERE USER = 'system user' +AND STATE = 'debug sync point: now' +AND INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER'; + +--let $ddl_applier_id = `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now'` + +# The DDL has not yet been applied +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; + +# The DDL applier thread can not be killed +--disable_query_log +--replace_regex /[0-9]+/N/ +--error ER_KILL_DENIED_ERROR +--eval KILL CONNECTION $ddl_applier_id; + +--replace_regex /[0-9]+/N/ +--error ER_KILL_DENIED_ERROR +--eval KILL QUERY $ddl_applier_id; +--enable_query_log + +# Then, if we unblock the applier thread +--disable_query_log +--eval SET GLOBAL debug = '$debug_orig'; +--enable_query_log +SET DEBUG_SYNC= 'now SIGNAL signal.alter_opened_table'; +SET SESSION wsrep_sync_wait = 7; + +# ... the applier thread will terminate +--let $wait_condition = SELECT COUNT(*) = 3 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' +--source include/wait_condition.inc + +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST +WHERE USER = 'system user' +AND STATE = 'debug sync point: now' +AND INFO = 'ALTER TABLE t1 ADD COLUMN f2 INTEGER'; + +# The alter has now been applied +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; + +# Both DDL and DML are now possible + +INSERT INTO t1 VALUES (1,2); +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN t3 INTEGER; + +DROP TABLE t1; +DROP TABLE t2; + +--connection node_1 +--reap diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_sst_slave.test b/mysql-test/suite/galera_ee/t/galera_nbo_sst_slave.test new file mode 100644 index 00000000000..38be1674f97 --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_nbo_sst_slave.test @@ -0,0 +1,89 @@ +# +# This test attempts to perform SST on slave while DDL is still in progress on master +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/big_test.inc + +# Shut down node #2 and wait until it is completely gone +--connection node_2 +--let $MYSQLD2_DATADIR = `SELECT @@datadir` +--source include/shutdown_mysqld.inc +--sleep 2 + +--connection node_1 +--source include/wait_until_connected_again.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +# Remove grastate.dat from node #2 so that SST is guaranteed +--remove_file $MYSQLD2_DATADIR/grastate.dat + +# Begin an ALTER and block + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; +SET SESSION wsrep_osu_method=NBO; +--send ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER; + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER' AND STATE = 'debug sync point: now'; +--source include/wait_condition.inc + +# Attempt to restart node #2. With grastate.dat removed, SST should be attempted + +--connection node_2 +--exec echo "restart" > $_expect_file_name +--sleep 1 +--exec echo "wait" > $_expect_file_name +--sleep 5 + +--connection node_1a +--let $assert_text= Master should report that it can not donate SST +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let $assert_select= Non-blocking operation in progress, cannot donate SST +--let $assert_match= Non-blocking operation in progress, cannot donate SST +--source include/assert_grep.inc + +--let $assert_text= Slave should report that it could not join +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.2.err +--let $assert_select= Will never receive state +--let $assert_match= Will never receive state +--source include/assert_grep.inc + + +# Restart node_2 again, now with the DDL out of the way +--connection node_1a +SET GLOBAL debug = ''; +SET DEBUG_SYNC='now SIGNAL signal.alter_locked_tables_inplace'; + +--connection node_1 +--reap + +--connection node_2 +--source include/start_mysqld.inc +SHOW CREATE TABLE t1; + +--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status' +--source include/wait_condition.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +SET SESSION wsrep_osu_method=TOI; +DROP TABLE t1; + +--connection node_1 +CALL mtr.add_suppression("Non-blocking operation in progress, cannot donate SST"); +CALL mtr.add_suppression("Resource temporarily unavailable"); + +--connection node_2 +CALL mtr.add_suppression("Resource temporarily unavailable"); +CALL mtr.add_suppression("Will never receive state"); +CALL mtr.add_suppression("terminated unexpectedly"); diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_temporary_table-master.opt b/mysql-test/suite/galera_ee/t/galera_nbo_temporary_table-master.opt new file mode 100644 index 00000000000..4a13f55f2dc --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_nbo_temporary_table-master.opt @@ -0,0 +1,2 @@ +--log-slave-updates --log-bin + diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_temporary_table.test b/mysql-test/suite/galera_ee/t/galera_nbo_temporary_table.test new file mode 100644 index 00000000000..a8db548688a --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_nbo_temporary_table.test @@ -0,0 +1,37 @@ +# +# Test that performing NBO operations on TEMPORARY tables does not cause +# undue replication or binlogging +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +RESET MASTER; + +--connection node_2 +RESET MASTER; + +--connection node_1 +CREATE TEMPORARY TABLE t1 (f1 INTEGER, f2 INTEGER); + +SET SESSION wsrep_OSU_method=NBO; +ALTER TABLE t1 LOCK=SHARED, DROP COLUMN f2; + +--connection node_2 +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; + +--connection node_1 +--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/ +--replace_column 2 <Pos> 5 <End_log_pos> +SHOW BINLOG EVENTS IN '0.000001' FROM 120; + +--connection node_2 +--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/ +--replace_column 2 <Pos> 5 <End_log_pos> +SHOW BINLOG EVENTS IN '0.000001' FROM 120; + +--connection node_1 +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; + diff --git a/mysql-test/suite/galera_ee/t/galera_nbo_unsupported.test b/mysql-test/suite/galera_ee/t/galera_nbo_unsupported.test new file mode 100644 index 00000000000..1d80c0614d7 --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_nbo_unsupported.test @@ -0,0 +1,42 @@ +# +# Test that various statements not supported under NBO return error +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; + +SET SESSION wsrep_osu_method='NBO'; + +--error ER_NOT_SUPPORTED_YET +CREATE TABLE t2 (f1 INTEGER); + +--error ER_NOT_SUPPORTED_YET +RENAME TABLE t1 TO t2; + +--error ER_NOT_SUPPORTED_YET +ALTER TABLE t1 LOCK=DEFAULT, ADD COLUMN f2 INTEGER; + +--error ER_NOT_SUPPORTED_YET +ALTER TABLE t2 LOCK=NONE, ADD COLUMN f2 INTEGER; + +--error ER_NOT_SUPPORTED_YET +DROP TABLE t1; + +--error ER_NOT_SUPPORTED_YET +REPAIR TABLE t1; + +--error ER_NOT_SUPPORTED_YET +CREATE USER u1 IDENTIFIED BY 'p1'; + +--error ER_NOT_SUPPORTED_YET +DROP USER u1; + +SET SESSION wsrep_osu_method=TOI; + +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CALL mtr.add_suppression('ALTER TABLE isolation failure'); diff --git a/mysql-test/suite/galera_ee/t/galera_vote_rejoin_ddl.cnf b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_ddl.cnf new file mode 100644 index 00000000000..8f0fa4a30bc --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_ddl.cnf @@ -0,0 +1,5 @@ +!include ../galera_4nodes.cnf + +[mysqld] +wsrep-ignore-apply-errors=0 + diff --git a/mysql-test/suite/galera_ee/t/galera_vote_rejoin_ddl.test b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_ddl.test new file mode 100644 index 00000000000..1aff71a454e --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_ddl.test @@ -0,0 +1,87 @@ +# +# Test the case where a node that dropped prior to an inconsistency vote is able +# to rejoin via IST after the vote is complete +# + +--source include/galera_cluster.inc +--source include/big_test.inc + +# Isolate node #4 +--connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4 +--connection node_4 +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1'; + +# Wait for node #4 to leave cluster +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +# Introduce inconsistency on node #3 +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3 +SET SESSION wsrep_on=OFF; +CREATE TABLE t1 (f1 INTEGER); +SET SESSION wsrep_on=ON; +DROP TABLE t1; + +# Wait for node #3 to be voted out +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +# Do some more stuff on the cluster to add to the IST stream +--connection node_1 +CREATE TABLE t2 (f1 INTEGER); + +# Rejoin node #4 +--connection node_4 +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0'; +--source include/galera_wait_ready.inc + +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +# Confirm that all is good +--connection node_4 +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2'; + +# Rejoin node #3 +--connection node_3 +SET SESSION wsrep_on=OFF; +--source include/kill_galera.inc +--sleep 1 +--echo Starting mysqld +--source include/start_mysqld.inc + +# Confirm node #3 has rejoined +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +# Confirm that all is good and all nodes have identical data + +--connection node_1 +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2'; +CALL mtr.add_suppression("Slave SQL: Error 'Unknown table"); + +--connection node_2 +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2'; +CALL mtr.add_suppression("Slave SQL: Error 'Unknown table"); + +--connection node_3 +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2'; +CALL mtr.add_suppression("inconsistent with group"); + +--connection node_4 +SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2'; + +DROP TABLE t2; diff --git a/mysql-test/suite/galera_ee/t/galera_vote_rejoin_dml.cnf b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_dml.cnf new file mode 100644 index 00000000000..b2cba42c0bd --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_dml.cnf @@ -0,0 +1,4 @@ +!include ../galera_4nodes.cnf + +[mysqld] +wsrep-ignore-apply-errors=0 diff --git a/mysql-test/suite/galera_ee/t/galera_vote_rejoin_dml.test b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_dml.test new file mode 100644 index 00000000000..8dd910c85ee --- /dev/null +++ b/mysql-test/suite/galera_ee/t/galera_vote_rejoin_dml.test @@ -0,0 +1,91 @@ +# +# Test the case where a node that dropped prior to an inconsistency vote is able +# to rejoin via IST after the vote is complete +# + +--source include/galera_cluster.inc +--source include/big_test.inc + +# Isolate node #4 +--connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4 +--connection node_4 +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1'; + +# Wait for node #4 to leave cluster +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 'A'); + +# Introduce inconsistency on node #3 +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_3 +SET SESSION wsrep_on=OFF; +INSERT INTO t1 VALUES (2, 'B'); +SET SESSION wsrep_on=ON; +DELETE FROM t1 WHERE f1 = 2; + +# Wait for node #3 to be voted out +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +# Rejoin node #4 +--connection node_4 +--source include/wsrep_wait_disconnect.inc +SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0'; +--source include/galera_wait_ready.inc + +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +# Confirm that all is good +--connection node_4 +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A'; +SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B'; + +# Rejoin node #3 +--connection node_3 +SET SESSION wsrep_on=OFF; +--source include/kill_galera.inc +--sleep 1 +--echo Starting mysqld +--source include/start_mysqld.inc + +# Confirm node #3 has rejoined +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +# Confirm that all is good and all nodes have identical data + +--connection node_1 +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A'; +SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B'; +CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows"); +CALL mtr.add_suppression("Delete_rows apply failed"); + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A'; +SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B'; +CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows"); +CALL mtr.add_suppression("Delete_rows apply failed"); + +--connection node_3 +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A'; +SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B'; +CALL mtr.add_suppression("inconsistent with group"); + +--connection node_4 +--source include/galera_wait_ready.inc +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'A'; +SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'B'; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/t/mysql-wsrep-features#127.test b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#127.test new file mode 100644 index 00000000000..ddbf77838ce --- /dev/null +++ b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#127.test @@ -0,0 +1,16 @@ +# NB-DDL: Assertion `thd == _current_thd()' failed in check_stack_overrun + +--source include/galera_cluster.inc + + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER); +SET GLOBAL wsrep_OSU_method=NBO; + +--connection node_2 +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER; + +--connection node_1 +SET GLOBAL wsrep_OSU_method=TOI; +DROP TABLE t1; + diff --git a/mysql-test/suite/galera_ee/t/mysql-wsrep-features#128-master.opt b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#128-master.opt new file mode 100644 index 00000000000..d9d2edc09af --- /dev/null +++ b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#128-master.opt @@ -0,0 +1 @@ +--wsrep_OSU_method=NBO diff --git a/mysql-test/suite/galera_ee/t/mysql-wsrep-features#128.test b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#128.test new file mode 100644 index 00000000000..33d15f10ec3 --- /dev/null +++ b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#128.test @@ -0,0 +1,11 @@ +# NB-DDL: Assertion `thd->wsrep_nbo_ctx' failed in lock_table_names when starting server with --wsrep-OSU-method=NBO + +--source include/galera_cluster.inc + +SET SESSION wsrep_OSU_method=TOI; +CREATE TABLE t1 (f1 INTEGER); +SET SESSION wsrep_OSU_method=NBO; +ALTER TABLE t1 LOCK=SHARED, ADD COLUMN f2 INTEGER; +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; +SET SESSION wsrep_OSU_method=NBO; diff --git a/mysql-test/suite/galera_ee/t/mysql-wsrep-features#131.test b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#131.test new file mode 100644 index 00000000000..f7e2ccbf828 --- /dev/null +++ b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#131.test @@ -0,0 +1,38 @@ +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET SESSION wsrep_osu_method=NBO; + +--connection node_2 +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; + +--connection node_1 +--send ALTER TABLE t1 ALGORITHM=INPLACE, LOCK=SHARED, ADD PRIMARY KEY (f1); + +--connection node_2 +SET SESSION wsrep_sync_wait=0; + +# Wait for the ALTER to block in sync point +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now'; +--source include/wait_condition.inc + +--send INSERT INTO t1 VALUES (1); + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a + +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; + +--connection node_2 +--error ER_DUP_ENTRY +--reap + +--connection node_1 +--reap + +SET SESSION wsrep_OSU_method=TOI; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_ee/t/mysql-wsrep-features#132.test b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#132.test new file mode 100644 index 00000000000..d7110d0791a --- /dev/null +++ b/mysql-test/suite/galera_ee/t/mysql-wsrep-features#132.test @@ -0,0 +1,39 @@ +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + + +CREATE TABLE t1 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +SET SESSION wsrep_osu_method=NBO; + +--connection node_2 +SET GLOBAL debug = 'd,sync.alter_locked_tables_inplace'; + +--connection node_1 +--send ALTER TABLE t1 ADD PRIMARY KEY (f1), ALGORITHM=INPLACE, LOCK=SHARED; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: now' +--source include/wait_condition.inc + +SET SESSION wsrep_sync_wait=0; +INSERT INTO t2 VALUES (1); + +SET DEBUG_SYNC= 'now SIGNAL signal.alter_locked_tables_inplace'; +SET GLOBAL debug = ''; + +--connection node_1 +--reap + +SELECT COUNT(*) = 1 FROM t2; + +--connection node_2 +SELECT COUNT(*) = 1 FROM t2; + +DROP TABLE t1; +DROP TABLE t2; + + diff --git a/mysql-test/suite/galera_sr/galera_2nodes.cnf b/mysql-test/suite/galera_sr/galera_2nodes.cnf new file mode 100644 index 00000000000..0412b5654dd --- /dev/null +++ b/mysql-test/suite/galera_sr/galera_2nodes.cnf @@ -0,0 +1 @@ +!include ../galera/galera_2nodes.cnf diff --git a/mysql-test/suite/galera_sr/my.cnf b/mysql-test/suite/galera_sr/my.cnf new file mode 100644 index 00000000000..ca163a540d9 --- /dev/null +++ b/mysql-test/suite/galera_sr/my.cnf @@ -0,0 +1 @@ +!include galera_2nodes.cnf diff --git a/mysql-test/suite/galera_sr/r/GCF-1008.result b/mysql-test/suite/galera_sr/r/GCF-1008.result new file mode 100644 index 00000000000..a0f320c7dd0 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-1008.result @@ -0,0 +1,50 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +START TRANSACTION; +INSERT INTO t1 VALUES (1, 'x'); +SET GLOBAL wsrep_provider_options = 'dbug=d,before_local_commit_monitor_enter'; +COMMIT; +SET SESSION wsrep_sync_wait = 0; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_trx_fragment_size = 1; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +REPLACE INTO t1 VALUES (1,'y'); +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SET GLOBAL wsrep_provider_options = 'signal=before_local_commit_monitor_enter'; +SET GLOBAL wsrep_provider_options = 'dbug='; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +START TRANSACTION; +INSERT INTO t1 VALUES (1, 'x'); +SET GLOBAL wsrep_provider_options = 'dbug=d,before_certify_apply_monitor_enter'; +COMMIT; +SET SESSION wsrep_sync_wait = 0; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_trx_fragment_size = 1; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +REPLACE INTO t1 VALUES (1,'y'); +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SET GLOBAL wsrep_provider_options = 'signal=before_certify_apply_monitor_enter'; +SET GLOBAL wsrep_provider_options = 'dbug='; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/GCF-1018.result b/mysql-test/suite/galera_sr/r/GCF-1018.result new file mode 100644 index 00000000000..fc624aec10d --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-1018.result @@ -0,0 +1,15 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB; +INSERT INTO t1 (f2) VALUES ('a'); +INSERT INTO t1 (f2) VALUES ('b'); +INSERT INTO t1 (f2) VALUES ('c'); +SET SESSION wsrep_sync_wait = 0; +SET GLOBAL wsrep_provider_options = 'dbug=d,after_certify_apply_monitor_enter'; +SET SESSION wsrep_trx_fragment_size = 64; +DELETE FROM t1 ORDER BY f1 DESC LIMIT 2;; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +INSERT INTO t1 (f2) VALUES ('d'),('e'); +SET GLOBAL wsrep_provider_options = 'signal=after_certify_apply_monitor_enter'; +SET GLOBAL wsrep_provider_options = 'dbug='; +Got one of the listed errors +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/GCF-1018B.result b/mysql-test/suite/galera_sr/r/GCF-1018B.result new file mode 100644 index 00000000000..b1c7efed7a6 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-1018B.result @@ -0,0 +1,8 @@ +SET SESSION wsrep_sync_wait = 0; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 64; +SET SESSION innodb_lock_wait_timeout = 1000; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_trx_fragment_size = 64; +SET SESSION innodb_lock_wait_timeout = 1000; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/GCF-1043A.result b/mysql-test/suite/galera_sr/r/GCF-1043A.result new file mode 100644 index 00000000000..1aef0ddd660 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-1043A.result @@ -0,0 +1,15 @@ +Running a concurrent test with the following queries: +DELETE FROM t1 +REPLACE INTO t1 VALUES (1,'y'),(2,'x') +REPLACE INTO t1 VALUES (1,'y'),(2,'y'),(3,'y') +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_trx_fragment_size = 1;;; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_trx_fragment_size = 1;;; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_trx_fragment_size = 1;;; +include/diff_servers.inc [servers=1 2] +DROP TABLE t1; +Concurrent test end diff --git a/mysql-test/suite/galera_sr/r/GCF-1043B.result b/mysql-test/suite/galera_sr/r/GCF-1043B.result new file mode 100644 index 00000000000..c86857b0a3f --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-1043B.result @@ -0,0 +1,15 @@ +Running a concurrent test with the following queries: +DELETE FROM t1 +INSERT INTO t1 VALUES (1,'y'),(2,'x') +UPDATE t1 SET f2 = 'y' WHERE f1 = 1 OR f1 = 2; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_trx_fragment_size = 1;;; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_trx_fragment_size = 1;;; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_trx_fragment_size = 1;;; +include/diff_servers.inc [servers=1 2] +DROP TABLE t1; +Concurrent test end diff --git a/mysql-test/suite/galera_sr/r/GCF-1051.result b/mysql-test/suite/galera_sr/r/GCF-1051.result new file mode 100644 index 00000000000..92e815a3733 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-1051.result @@ -0,0 +1,37 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +SAVEPOINT A; +INSERT INTO t1 VALUES (1); +ROLLBACK TO SAVEPOINT A; +COMMIT; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=OFF; +SAVEPOINT A; +INSERT INTO t1 VALUES (2); +ROLLBACK TO SAVEPOINT A; +COMMIT; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/GCF-1060.result b/mysql-test/suite/galera_sr/r/GCF-1060.result new file mode 100644 index 00000000000..bddb3182e46 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-1060.result @@ -0,0 +1,15 @@ +Running a concurrent test with the following queries: +TRUNCATE TABLE t1 +INSERT INTO t1 VALUE (1,'x'),(2,'x'),(3,'x') +INSERT INTO t1 VALUE (4, 'z'); +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_trx_fragment_size = 1;;; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_trx_fragment_size = 1;;; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_trx_fragment_size = 1;;; +include/diff_servers.inc [servers=1 2] +DROP TABLE t1; +Concurrent test end diff --git a/mysql-test/suite/galera_sr/r/GCF-437.result b/mysql-test/suite/galera_sr/r/GCF-437.result new file mode 100644 index 00000000000..5d04022655f --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-437.result @@ -0,0 +1,12 @@ +CREATE TABLE ten (f1 INTEGER) ENGINE=MyISAM; +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(512)) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 2 * 1024 * 1024; +INSERT INTO t1 (f2) SELECT REPEAT('x', 512) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5; +ERROR HY000: Writing one row to the row-based binary log failed +CALL mtr.add_suppression("InnoDB: The total blob data length*"); +CALL mtr.add_suppression("WSREP: Error writing into wsrep_schema.SR: 139"); +CALL mtr.add_suppression("WSREP: Failed to write to frag table: 1"); +CALL mtr.add_suppression("WSREP: Failed to append frag to persistent storage"); +DROP TABLE t1; +DROP table ten; diff --git a/mysql-test/suite/galera_sr/r/GCF-561.result b/mysql-test/suite/galera_sr/r/GCF-561.result new file mode 100644 index 00000000000..a3c7ab585e4 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-561.result @@ -0,0 +1,42 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1, 1); +INSERT INTO t1 VALUES (2, 2); +INSERT INTO t1 VALUES (3, 3); +INSERT INTO t1 VALUES (4, 4); +INSERT INTO t1 VALUES (5, 5); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +ALTER TABLE t1 DROP COLUMN f2; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +INSERT INTO t1 VALUES (6, 6); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +INSERT INTO t1 VALUES (6, 6); +ERROR 21S01: Column count doesn't match value count at row 1 +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +COMMIT; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/GCF-571.result b/mysql-test/suite/galera_sr/r/GCF-571.result new file mode 100644 index 00000000000..502c7393289 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-571.result @@ -0,0 +1,56 @@ +SET AUTOCOMMIT=OFF; +CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +START TRANSACTION; +INSERT INTO t1 VALUES ('%abcdef%'); +INSERT INTO t1 VALUES ('%abcdef%'); +INSERT INTO t1 VALUES ('%abcdef%'); +INSERT INTO t1 VALUES ('%abcdef%'); +SAVEPOINT A; +INSERT INTO t1 VALUES ('xyzxyz'); +INSERT INTO t1 VALUES ('xyzxyz'); +INSERT INTO t1 VALUES ('xyzxyz'); +INSERT INTO t1 VALUES ('xyzxyz'); +INSERT INTO t1 VALUES ('xyzxyz'); +SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%abcdef%'; +COUNT(*) > 0 +1 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%xyz%'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%SAVEPOINT `A`%'; +COUNT(*) = 1 +1 +ROLLBACK TO SAVEPOINT A; +SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%abcdef%'; +COUNT(*) > 0 +1 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%xyz%'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%SAVEPOINT `A`%'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%ROLLBACK TO `A`%'; +COUNT(*) = 1 +1 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%abcdef%'; +COUNT(*) > 0 +1 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%xyz%'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%SAVEPOINT `A`%'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%ROLLBACK TO `A`%'; +COUNT(*) = 1 +1 +ROLLBACK; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/GCF-572.result b/mysql-test/suite/galera_sr/r/GCF-572.result new file mode 100644 index 00000000000..8836f3777d6 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-572.result @@ -0,0 +1,29 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(10)) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +START TRANSACTION; +INSERT INTO t1 VALUES (1, 'node1'); +INSERT INTO t1 VALUES (5, 'node2'); +INSERT INTO t1 VALUES (5, 'node1'); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM t1; +f1 f2 +5 node2 +SET SESSION wsrep_trx_fragment_size = 10000; +START TRANSACTION; +INSERT INTO t1 VALUE (10, 'node1'); +SELECT * FROM wsrep_schema.SR; +node_uuid trx_id seqno flags frag +INSERT INTO t1 VALUES(15, 'node2'); +SELECT * FROM t1; +f1 f2 +5 node2 +10 node1 +INSERT INTO t1 VALUES(15, 'node1'); +ERROR 23000: Duplicate entry '15' for key 'PRIMARY' +COMMIT; +SELECT * FROM t1; +f1 f2 +5 node2 +10 node1 +15 node2 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/GCF-574.result b/mysql-test/suite/galera_sr/r/GCF-574.result new file mode 100644 index 00000000000..bbf817c8c6c --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-574.result @@ -0,0 +1,11 @@ +CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +SET SESSION wsrep_trx_fragment_size = 1; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; +wsrep_last_committed_delta +1 +SELECT COUNT(*) = 10000 FROM t1; +COUNT(*) = 10000 +1 +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera_sr/r/GCF-580.result b/mysql-test/suite/galera_sr/r/GCF-580.result new file mode 100644 index 00000000000..83cbdde092a --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-580.result @@ -0,0 +1,11 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +last_committed_matches_fragment_count +1 +COMMIT; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/GCF-585.result b/mysql-test/suite/galera_sr/r/GCF-585.result new file mode 100644 index 00000000000..6305c4ad31e --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-585.result @@ -0,0 +1,25 @@ +create table t1 (f1 integer primary key) engine=innodb; +set autocommit=off; +set session wsrep_trx_fragment_size=1; +start transaction; +insert into t1 values (1); +insert into t1 values (2),(1); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +alter table t1 drop primary key; +drop table t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); +SET SESSION wsrep_trx_fragment_size=1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +update t1 set f1 = 100 where f1 = 10; +INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20); +SET SESSION wsrep_trx_fragment_size=1; +SET SESSION innodb_lock_wait_timeout=1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +delete from t1 where f1 > 10; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +delete from t1 where f1 > 10 and f1 < 100; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/GCF-597.result b/mysql-test/suite/galera_sr/r/GCF-597.result new file mode 100644 index 00000000000..e2f35e95e28 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-597.result @@ -0,0 +1,15 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +SET wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +ROLLBACK; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/GCF-620.result b/mysql-test/suite/galera_sr/r/GCF-620.result new file mode 100644 index 00000000000..ac02d49e086 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-620.result @@ -0,0 +1,14 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size = 200; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +SAVEPOINT A; +INSERT INTO t1 VALUES (1); +ROLLBACK TO SAVEPOINT A; +COMMIT; +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/GCF-623.result b/mysql-test/suite/galera_sr/r/GCF-623.result new file mode 100644 index 00000000000..790eb1fd89d --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-623.result @@ -0,0 +1,22 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/GCF-627.result b/mysql-test/suite/galera_sr/r/GCF-627.result new file mode 100644 index 00000000000..6c8fad03ed4 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-627.result @@ -0,0 +1,18 @@ +CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER); +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1, 'a'); +DROP TABLE t1; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +INSERT INTO t1 VALUES (2); +ERROR 42S02: Table 'test.t1' doesn't exist +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t2; diff --git a/mysql-test/suite/galera_sr/r/GCF-845.result b/mysql-test/suite/galera_sr/r/GCF-845.result new file mode 100644 index 00000000000..3fa6d1bb704 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-845.result @@ -0,0 +1,14 @@ +CREATE TABLE IF NOT EXISTS t1 (f1 INTEGER) ENGINE = InnoDB; +SET SESSION AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size = 1; +INSERT INTO t1 VALUES (161); +COMMIT; +DELETE FROM t1 WHERE f1 > 13; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; +include/assert_grep.inc [No BF-BF log line found] diff --git a/mysql-test/suite/galera_sr/r/GCF-851.result b/mysql-test/suite/galera_sr/r/GCF-851.result new file mode 100644 index 00000000000..6da002ec081 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-851.result @@ -0,0 +1,24 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION WSREP_TRX_FRAGMENT_SIZE=1; +SET SESSION AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (10); +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +START TRANSACTION; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) > 0 FROM t1; +COUNT(*) > 0 +1 +SELECT COUNT(*) > 0 FROM t1; +COUNT(*) > 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/GCF-867.result b/mysql-test/suite/galera_sr/r/GCF-867.result new file mode 100644 index 00000000000..0aa19bbd537 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-867.result @@ -0,0 +1,2 @@ +CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/GCF-889.result b/mysql-test/suite/galera_sr/r/GCF-889.result new file mode 100644 index 00000000000..b5402f105a4 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-889.result @@ -0,0 +1,18 @@ +SET GLOBAL wsrep_ignore_apply_errors = 2; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_on = OFF; +INSERT INTO t1 VALUES (1); +SET SESSION wsrep_on = ON; +SET SESSION wsrep_trx_fragment_size = 1; +DELETE FROM t1 WHERE f1 = 1; +SET SESSION wsrep_trx_fragment_size = 0; +INSERT INTO t1 VALUES (1); +SELECT COUNT(*) = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1; +COUNT(*) = 1 +1 +CALL mtr.add_suppression("Could not execute Delete_rows event on table"); +SET GLOBAL wsrep_ignore_apply_errors = 7; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/GCF-900.result b/mysql-test/suite/galera_sr/r/GCF-900.result new file mode 100644 index 00000000000..e4eab9fbebe --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-900.result @@ -0,0 +1,13 @@ +CREATE TABLE t1 (f1 INT PRIMARY KEY, f2 INT) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 128; +START TRANSACTION; +INSERT INTO t1 VALUES (1, 0); +SET SESSION wsrep_trx_fragment_size = 1; +START TRANSACTION; +INSERT INTO t1 VALUES (2, 0); +ALTER TABLE t1 DROP COLUMN f2; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +INSERT INTO t1 VALUES (3, 0); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera-features#56.result b/mysql-test/suite/galera_sr/r/galera-features#56.result new file mode 100644 index 00000000000..16975217838 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera-features#56.result @@ -0,0 +1,21 @@ +SET SESSION wsrep_trx_fragment_size = 1; +CREATE TABLE ten (f1 INTEGER); +INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); +CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 INTEGER) Engine=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET GLOBAL wsrep_slave_threads = 4; +SET SESSION wsrep_trx_fragment_size = 1; +INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;; +INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;; +INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;; +SELECT COUNT(*) = 30000 FROM t1; +COUNT(*) = 30000 +1 +SELECT COUNT(DISTINCT f1) = 30000 FROM t1; +COUNT(DISTINCT f1) = 30000 +1 +SELECT COUNT(*) = 6 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'; +COUNT(*) = 6 +1 +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_bf_abort.result b/mysql-test/suite/galera_sr/r/galera_sr_bf_abort.result new file mode 100644 index 00000000000..ad274b0cb7f --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_bf_abort.result @@ -0,0 +1,448 @@ +SET SESSION wsrep_sync_wait = 0; +galera_sr_bf_abort_at_commit = 0 +after_replicate_sync +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; +f1 +1 +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,after_replicate_sync'; +INSERT INTO t1 VALUES (3); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync'; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +ROLLBACK; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +local_monitor_master_enter_sync +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; +f1 +1 +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync'; +INSERT INTO t1 VALUES (3); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync'; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +ROLLBACK; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +apply_monitor_master_enter_sync +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; +f1 +1 +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_master_enter_sync'; +INSERT INTO t1 VALUES (3); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_master_enter_sync'; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +ROLLBACK; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +commit_monitor_master_enter_sync +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; +f1 +1 +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync'; +INSERT INTO t1 VALUES (3); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync'; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +ROLLBACK; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +galera_sr_bf_abort_at_commit = 1 +after_replicate_sync +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; +f1 +1 +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,after_replicate_sync'; +COMMIT; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync'; +ROLLBACK; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +local_monitor_master_enter_sync +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; +f1 +1 +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync'; +COMMIT; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync'; +ROLLBACK; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +apply_monitor_master_enter_sync +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; +f1 +1 +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_master_enter_sync'; +COMMIT; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_master_enter_sync'; +ROLLBACK; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +commit_monitor_master_enter_sync +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; +f1 +1 +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (2); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync'; +COMMIT; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync'; +ROLLBACK; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT * FROM t1; +f1 +1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +CALL mtr.add_suppression("WSREP: fragment replication failed: 1"); diff --git a/mysql-test/suite/galera_sr/r/galera_sr_blob.result b/mysql-test/suite/galera_sr/r/galera_sr_blob.result new file mode 100644 index 00000000000..c1c51f843c4 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_blob.result @@ -0,0 +1,15 @@ +CREATE TABLE t1 (f1 TEXT) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (REPEAT('x', 65535)); +wsrep_last_committed_delta +1 +COMMIT; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT LENGTH(f1) = 65535 FROM t1; +LENGTH(f1) = 65535 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_cc_master.result b/mysql-test/suite/galera_sr/r/galera_sr_cc_master.result new file mode 100644 index 00000000000..35b014979bb --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_cc_master.result @@ -0,0 +1,45 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +SET GLOBAL wsrep_cluster_address = ''; +INSERT INTO t1 VALUES (6); +Got one of the listed errors +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT * FROM wsrep_schema.SR; +node_uuid trx_id seqno flags frag +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +COMMIT; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; +CALL mtr.add_suppression("WSREP: failed to send SR rollback for"); diff --git a/mysql-test/suite/galera_sr/r/galera_sr_cc_slave.result b/mysql-test/suite/galera_sr/r/galera_sr_cc_slave.result new file mode 100644 index 00000000000..a2c61693c61 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_cc_slave.result @@ -0,0 +1,46 @@ +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +SET GLOBAL wsrep_cluster_address = ''; +INSERT INTO t1 VALUES (6); +INSERT INTO t1 VALUES (7); +INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (9); +INSERT INTO t1 VALUES (10); +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +INSERT INTO t1 VALUES (11); +INSERT INTO t1 VALUES (12); +INSERT INTO t1 VALUES (13); +INSERT INTO t1 VALUES (14); +INSERT INTO t1 VALUES (16); +COMMIT; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_concurrent.result b/mysql-test/suite/galera_sr/r/galera_sr_concurrent.result new file mode 100644 index 00000000000..60cf5ca2633 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_concurrent.result @@ -0,0 +1,28 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t2 VALUES (1); +INSERT INTO t2 VALUES (2); +INSERT INTO t2 VALUES (3); +INSERT INTO t2 VALUES (4); +INSERT INTO t2 VALUES (5); +COMMIT; +COMMIT; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SELECT COUNT(*) = 5 FROM t2; +COUNT(*) = 5 +1 +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_conflict.result b/mysql-test/suite/galera_sr/r/galera_sr_conflict.result new file mode 100644 index 00000000000..be28892edbb --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_conflict.result @@ -0,0 +1,14 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +INSERT INTO t1 VALUES(1);; +COMMIT; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit.result b/mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit.result new file mode 100644 index 00000000000..ef68cd7ade0 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit.result @@ -0,0 +1,22 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +COMMIT; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit2.result b/mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit2.result new file mode 100644 index 00000000000..d2e8bc592bf --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit2.result @@ -0,0 +1,19 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +INSERT INTO t1 VALUES (5);; +COMMIT; +ERROR 23000: Duplicate entry '5' for key 'PRIMARY' +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_conflict_with_rollback_master.result b/mysql-test/suite/galera_sr/r/galera_sr_conflict_with_rollback_master.result new file mode 100644 index 00000000000..3f735746d95 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_conflict_with_rollback_master.result @@ -0,0 +1,22 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +ROLLBACK; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_ddl_master.result b/mysql-test/suite/galera_sr/r/galera_sr_ddl_master.result new file mode 100644 index 00000000000..ce94576cb95 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_ddl_master.result @@ -0,0 +1,41 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +INSERT INTO t1 VALUES (6); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +ROLLBACK; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES (1); +INSERT INTO t1 (f1) VALUES (2); +INSERT INTO t1 (f1) VALUES (3); +INSERT INTO t1 (f1) VALUES (4); +INSERT INTO t1 (f1) VALUES (5); +INSERT INTO t1 (f1) VALUES (6); +COMMIT; +SELECT COUNT(*) = 6 FROM t1; +COUNT(*) = 6 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 6 FROM t1; +COUNT(*) = 6 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_ddl_schema.result b/mysql-test/suite/galera_sr/r/galera_sr_ddl_schema.result new file mode 100644 index 00000000000..2227336cfad --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_ddl_schema.result @@ -0,0 +1,18 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1, 1); +INSERT INTO t1 VALUES (2, 2); +INSERT INTO t1 VALUES (3, 3); +INSERT INTO t1 VALUES (4, 4); +INSERT INTO t1 VALUES (5, 5); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +DROP SCHEMA test; +SELECT COUNT(*) = 0 FROM test.t1; +ERROR 42S02: Table 'test.t1' doesn't exist +INSERT INTO test.t1 VALUES (6, 6); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +INSERT INTO test.t1 VALUES (6, 6); +ERROR 42S02: Table 'test.t1' doesn't exist +CREATE SCHEMA test; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_ddl_slave.result b/mysql-test/suite/galera_sr/r/galera_sr_ddl_slave.result new file mode 100644 index 00000000000..a3c7ab585e4 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_ddl_slave.result @@ -0,0 +1,42 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1, 1); +INSERT INTO t1 VALUES (2, 2); +INSERT INTO t1 VALUES (3, 3); +INSERT INTO t1 VALUES (4, 4); +INSERT INTO t1 VALUES (5, 5); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +ALTER TABLE t1 DROP COLUMN f2; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +INSERT INTO t1 VALUES (6, 6); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +INSERT INTO t1 VALUES (6, 6); +ERROR 21S01: Column count doesn't match value count at row 1 +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +COMMIT; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_ddl_unrelated.result b/mysql-test/suite/galera_sr/r/galera_sr_ddl_unrelated.result new file mode 100644 index 00000000000..e9edcc9ea34 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_ddl_unrelated.result @@ -0,0 +1,34 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1, 1); +INSERT INTO t1 VALUES (2, 2); +INSERT INTO t1 VALUES (3, 3); +INSERT INTO t1 VALUES (4, 4); +INSERT INTO t1 VALUES (5, 5); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +ALTER TABLE t2 DROP COLUMN f2; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +INSERT INTO t1 VALUES (6, 6); +COMMIT; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 6 FROM t1; +COUNT(*) = 6 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_dupkey_error.result b/mysql-test/suite/galera_sr/r/galera_sr_dupkey_error.result new file mode 100644 index 00000000000..5ea1adee877 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_dupkey_error.result @@ -0,0 +1,36 @@ +CREATE TABLE t1 (f1 BLOB) ENGINE=InnoDB; +CREATE UNIQUE INDEX i1 ON t1 (f1(512)); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +SET SESSION wsrep_trx_fragment_size = 1024; +INSERT INTO t1 VALUES (REPEAT('a', 512)); +INSERT INTO t1 VALUES (REPEAT('b', 512)); +INSERT INTO t1 VALUES (REPEAT('c', 512)); +INSERT INTO t1 VALUES (REPEAT('d', 512)); +INSERT INTO t1 VALUES (REPEAT('e', 512)); +INSERT INTO t1 VALUES (REPEAT('f', 512)); +INSERT INTO t1 VALUES (REPEAT('c', 512)); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +INSERT INTO t1 VALUES (REPEAT('d', 512)); +INSERT INTO t1 VALUES (REPEAT('e', 512)); +INSERT INTO t1 VALUES (REPEAT('f', 512)); +COMMIT; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (REPEAT('a', 512)); +INSERT INTO t1 VALUES (REPEAT('b', 512)); +INSERT INTO t1 VALUES (REPEAT('c', 512)); +COMMIT; +SELECT COUNT(*) = 6 FROM t1; +COUNT(*) = 6 +1 +SELECT COUNT(*) = 6 FROM t1; +COUNT(*) = 6 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_fk_conflict.result b/mysql-test/suite/galera_sr/r/galera_sr_fk_conflict.result new file mode 100644 index 00000000000..839a3ef1f71 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_fk_conflict.result @@ -0,0 +1,34 @@ +CREATE TABLE grandparent ( +id INT NOT NULL PRIMARY KEY +) ENGINE=InnoDB; +CREATE TABLE parent ( +id INT NOT NULL PRIMARY KEY, +grandparent_id INT, +FOREIGN KEY (grandparent_id) +REFERENCES grandparent(id) +ON UPDATE CASCADE +) ENGINE=InnoDB; +CREATE TABLE child ( +id INT NOT NULL PRIMARY KEY, +grandparent_id INT, +FOREIGN KEY (grandparent_id) +REFERENCES parent(grandparent_id) +ON UPDATE CASCADE +) ENGINE=InnoDB; +INSERT INTO grandparent VALUES (1),(2),(3),(4); +INSERT INTO parent VALUES (1,1), (2,2); +INSERT INTO child VALUES (1,1), (2,2); +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size = 1; +START TRANSACTION; +UPDATE grandparent SET id = 5 WHERE id = 1; +SET SESSION innodb_lock_wait_timeout = 1; +UPDATE grandparent SET id = 10 WHERE id = 5; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +DELETE FROM child; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +COMMIT; +include/diff_servers.inc [servers=1 2] +DROP TABLE child; +DROP TABLE parent; +DROP TABLE grandparent; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_gtid.result b/mysql-test/suite/galera_sr/r/galera_sr_gtid.result new file mode 100644 index 00000000000..5e89752d7cb --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_gtid.result @@ -0,0 +1,65 @@ +CREATE TABLE t1 (f1 INT PRIMARY KEY); +SET SESSION wsrep_trx_fragment_size=1; +INSERT INTO t1 VALUES (1); +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SET SESSION wsrep_trx_fragment_size=1; +UPDATE t1 SET f1 = 2; +SET SESSION wsrep_trx_fragment_size=0; +SET SESSION wsrep_trx_fragment_size=0; +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +gtid_executed_equal +1 +SHOW BINLOG EVENTS IN 'mysqld-bin.000002' FROM 120; +Log_name Pos Event_type Server_id End_log_pos Info +mysqld-bin.000002 <Pos> Previous_gtids 1 <End_log_pos> <GTID>:1-2 +mysqld-bin.000002 <Pos> Gtid 1 <End_log_pos> SET @@SESSION.GTID_NEXT= '<GTID>:3' +mysqld-bin.000002 <Pos> Query 1 <End_log_pos> use `test`; CREATE TABLE t1 (f1 INT PRIMARY KEY) +mysqld-bin.000002 <Pos> Gtid 1 <End_log_pos> SET @@SESSION.GTID_NEXT= '<GTID>:4' +mysqld-bin.000002 <Pos> Query 1 <End_log_pos> BEGIN +mysqld-bin.000002 <Pos> Ignorable 1 <End_log_pos> # Unrecognized ignorable event +mysqld-bin.000002 <Pos> Query 1 <End_log_pos> COMMIT +mysqld-bin.000002 <Pos> Gtid 1 <End_log_pos> SET @@SESSION.GTID_NEXT= '<GTID>:5' +mysqld-bin.000002 <Pos> Query 1 <End_log_pos> BEGIN +mysqld-bin.000002 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1) +mysqld-bin.000002 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000002 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */ +mysqld-bin.000002 <Pos> Gtid 1 <End_log_pos> SET @@SESSION.GTID_NEXT= '<GTID>:6' +mysqld-bin.000002 <Pos> Query 1 <End_log_pos> BEGIN +mysqld-bin.000002 <Pos> Ignorable 1 <End_log_pos> # Unrecognized ignorable event +mysqld-bin.000002 <Pos> Query 1 <End_log_pos> COMMIT +mysqld-bin.000002 <Pos> Gtid 2 <End_log_pos> SET @@SESSION.GTID_NEXT= '<GTID>:7' +mysqld-bin.000002 <Pos> Query 2 <End_log_pos> BEGIN +mysqld-bin.000002 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t1) +mysqld-bin.000002 <Pos> Update_rows 2 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000002 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */ +SELECT 1 FROM DUAL; +1 +1 +SHOW BINLOG EVENTS IN 'mysqld-bin.000003' FROM 120; +Log_name Pos Event_type Server_id End_log_pos Info +mysqld-bin.000003 <Pos> Previous_gtids 2 <End_log_pos> <GTID>:1-2 +mysqld-bin.000003 <Pos> Gtid 1 <End_log_pos> SET @@SESSION.GTID_NEXT= '<GTID>:3' +mysqld-bin.000003 <Pos> Query 1 <End_log_pos> use `test`; CREATE TABLE t1 (f1 INT PRIMARY KEY) +mysqld-bin.000003 <Pos> Gtid 1 <End_log_pos> SET @@SESSION.GTID_NEXT= '<GTID>:4' +mysqld-bin.000003 <Pos> Query 1 <End_log_pos> BEGIN +mysqld-bin.000003 <Pos> Ignorable 1 <End_log_pos> # Unrecognized ignorable event +mysqld-bin.000003 <Pos> Query 1 <End_log_pos> COMMIT +mysqld-bin.000003 <Pos> Gtid 1 <End_log_pos> SET @@SESSION.GTID_NEXT= '<GTID>:5' +mysqld-bin.000003 <Pos> Query 1 <End_log_pos> BEGIN +mysqld-bin.000003 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1) +mysqld-bin.000003 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000003 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */ +mysqld-bin.000003 <Pos> Gtid 2 <End_log_pos> SET @@SESSION.GTID_NEXT= '<GTID>:6' +mysqld-bin.000003 <Pos> Query 2 <End_log_pos> BEGIN +mysqld-bin.000003 <Pos> Ignorable 2 <End_log_pos> # Unrecognized ignorable event +mysqld-bin.000003 <Pos> Query 2 <End_log_pos> COMMIT +mysqld-bin.000003 <Pos> Gtid 2 <End_log_pos> SET @@SESSION.GTID_NEXT= '<GTID>:7' +mysqld-bin.000003 <Pos> Query 2 <End_log_pos> BEGIN +mysqld-bin.000003 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t1) +mysqld-bin.000003 <Pos> Update_rows 2 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000003 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */ +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_insert_select.result b/mysql-test/suite/galera_sr/r/galera_sr_insert_select.result new file mode 100644 index 00000000000..2b85b5ec58c --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_insert_select.result @@ -0,0 +1,11 @@ +CREATE TABLE ten (f1 INTEGER); +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f2) SELECT REPEAT('a', 255) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +COMMIT; +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_kill_all_nobootstrap.result b/mysql-test/suite/galera_sr/r/galera_sr_kill_all_nobootstrap.result new file mode 100644 index 00000000000..8108e3b60cb --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_all_nobootstrap.result @@ -0,0 +1,21 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +Killing server ... +Killing server ... +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_kill_all_norecovery.result b/mysql-test/suite/galera_sr/r/galera_sr_kill_all_norecovery.result new file mode 100644 index 00000000000..6a274b7f2ae --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_all_norecovery.result @@ -0,0 +1,22 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +Killing server ... +Killing server ... +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_kill_all_pcrecovery.result b/mysql-test/suite/galera_sr/r/galera_sr_kill_all_pcrecovery.result new file mode 100644 index 00000000000..6a274b7f2ae --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_all_pcrecovery.result @@ -0,0 +1,22 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +Killing server ... +Killing server ... +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_kill_connection.result b/mysql-test/suite/galera_sr/r/galera_sr_kill_connection.result new file mode 100644 index 00000000000..4968ba1e0b6 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_connection.result @@ -0,0 +1,25 @@ +SET SESSION wsrep_trx_fragment_size = 1; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +COMMIT; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_kill_query.result b/mysql-test/suite/galera_sr/r/galera_sr_kill_query.result new file mode 100644 index 00000000000..f85870ec76a --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_query.result @@ -0,0 +1,17 @@ +SET SESSION wsrep_trx_fragment_size = 1; +CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6;; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +Killing query ... +ERROR 70100: Query execution was interrupted +INSERT INTO t1 SELECT 1 FROM ten AS t1, ten AS t2, ten AS t3; +SELECT COUNT(*) = 1000 FROM t1; +COUNT(*) = 1000 +1 +SELECT COUNT(*) = 1000 FROM t1; +COUNT(*) = 1000 +1 +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_kill_slave.result b/mysql-test/suite/galera_sr/r/galera_sr_kill_slave.result new file mode 100644 index 00000000000..758f306189c --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_slave.result @@ -0,0 +1,39 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +CREATE TABLE t2 (f1 INTEGER); +LOCK TABLE t2 WRITE; +INSERT INTO t2 VALUES (1); +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +Killing server ... +INSERT INTO t1 VALUES (6); +INSERT INTO t1 VALUES (7); +INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (9); +INSERT INTO t1 VALUES (10); +INSERT INTO t1 VALUES (11); +INSERT INTO t1 VALUES (12); +INSERT INTO t1 VALUES (13); +INSERT INTO t1 VALUES (14); +INSERT INTO t1 VALUES (15); +COMMIT; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 15 FROM t1; +COUNT(*) = 15 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_large_fragment.result b/mysql-test/suite/galera_sr/r/galera_sr_large_fragment.result new file mode 100644 index 00000000000..f1a445bf7d4 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_large_fragment.result @@ -0,0 +1,28 @@ +CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(512)) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1024 * 1024 * 10; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f2) SELECT REPEAT('x', 512) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5; +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) > 50000 FROM t1; +COUNT(*) > 50000 +1 +ROLLBACK; +SET SESSION wsrep_sync_wait = 0; +SET GLOBAL wsrep_provider_options = 'repl.causal_read_timeout=PT10M'; +SET SESSION wsrep_sync_wait = 7; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +COUNT(*) = 0 +1 +COUNT(*) = 0 +1 diff --git a/mysql-test/suite/galera_sr/r/galera_sr_load_data.result b/mysql-test/suite/galera_sr/r/galera_sr_load_data.result new file mode 100644 index 00000000000..1310ed318b6 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_load_data.result @@ -0,0 +1,8 @@ +SET SESSION wsrep_trx_fragment_size = 512; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SELECT COUNT(*) = 20000 FROM t1; +COUNT(*) = 20000 +1 +wsrep_last_committed_diff +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_load_data_splitting.result b/mysql-test/suite/galera_sr/r/galera_sr_load_data_splitting.result new file mode 100644 index 00000000000..b25a8877005 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_load_data_splitting.result @@ -0,0 +1,9 @@ +SET SESSION wsrep_trx_fragment_size = 512; +SET GLOBAL wsrep_load_data_splitting = TRUE; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SELECT COUNT(*) = 95000 FROM t1; +COUNT(*) = 95000 +1 +wsrep_last_committed_diff +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_log_bin.result b/mysql-test/suite/galera_sr/r/galera_sr_log_bin.result new file mode 100644 index 00000000000..22f44df1e6a --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_log_bin.result @@ -0,0 +1,87 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t3 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t4 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +RESET MASTER; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t2 VALUES (1); +RESET MASTER; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size = 1; +START TRANSACTION; +INSERT INTO t3 VALUES (1); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t4 VALUES (1); +INSERT INTO t1 VALUES (2); +COMMIT; +INSERT INTO t2 VALUES (2); +COMMIT; +INSERT INTO t3 VALUES (2); +COMMIT; +INSERT INTO t4 VALUES (2); +COMMIT; +SELECT COUNT(*) = 2 FROM t4; +COUNT(*) = 2 +1 +SHOW BINLOG EVENTS IN '0.000001' FROM 120; +Log_name Pos Event_type Server_id End_log_pos Info +0.000001 <Pos> Query 1 <End_log_pos> BEGIN +0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1) +0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1) +0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */ +0.000001 <Pos> Query 1 <End_log_pos> BEGIN +0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t2) +0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t2) +0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */ +0.000001 <Pos> Query 2 <End_log_pos> BEGIN +0.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t3) +0.000001 <Pos> Write_rows 2 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t3) +0.000001 <Pos> Write_rows 2 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */ +0.000001 <Pos> Query 2 <End_log_pos> BEGIN +0.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t4) +0.000001 <Pos> Write_rows 2 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t4) +0.000001 <Pos> Write_rows 2 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */ +SELECT COUNT(*) = 2 FROM t4; +COUNT(*) = 2 +1 +SHOW BINLOG EVENTS IN '0.000001' FROM 120; +Log_name Pos Event_type Server_id End_log_pos Info +0.000001 <Pos> Query 1 <End_log_pos> BEGIN +0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1) +0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1) +0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */ +0.000001 <Pos> Query 1 <End_log_pos> BEGIN +0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t2) +0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t2) +0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */ +0.000001 <Pos> Query 2 <End_log_pos> BEGIN +0.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t3) +0.000001 <Pos> Write_rows 2 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t3) +0.000001 <Pos> Write_rows 2 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */ +0.000001 <Pos> Query 2 <End_log_pos> BEGIN +0.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t4) +0.000001 <Pos> Write_rows 2 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t4) +0.000001 <Pos> Write_rows 2 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */ +DROP TABLE t1,t2,t3,t4; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_many_fragments.result b/mysql-test/suite/galera_sr/r/galera_sr_many_fragments.result new file mode 100644 index 00000000000..b44436c9cea --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_many_fragments.result @@ -0,0 +1,28 @@ +CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(512)) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f2) SELECT REPEAT('x', 512) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5; +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 100000 FROM t1; +COUNT(*) = 100000 +1 +ROLLBACK; +SET SESSION wsrep_sync_wait = 0; +SET GLOBAL wsrep_provider_options = 'repl.causal_read_timeout=PT10M'; +SET SESSION wsrep_sync_wait = 7; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +COUNT(*) = 0 +1 +COUNT(*) = 0 +1 diff --git a/mysql-test/suite/galera_sr/r/galera_sr_myisam.result b/mysql-test/suite/galera_sr/r/galera_sr_myisam.result new file mode 100644 index 00000000000..7d2a84814ba --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_myisam.result @@ -0,0 +1,11 @@ +CREATE TABLE t1 (f1 TEXT) ENGINE=MyISAM; +SET SESSION wsrep_trx_fragment_size = 1; +SET GLOBAL wsrep_replicate_myisam = TRUE; +INSERT INTO t1 VALUES (REPEAT('x', 65535)); +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT LENGTH(f1) = 65535 FROM t1; +LENGTH(f1) = 65535 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_mysqldump_sst.result b/mysql-test/suite/galera_sr/r/galera_sr_mysqldump_sst.result new file mode 100644 index 00000000000..9d47bddb9b4 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_mysqldump_sst.result @@ -0,0 +1,40 @@ +Setting SST method to mysqldump ... +GRANT ALL PRIVILEGES ON *.* TO 'sst'; +SET GLOBAL wsrep_sst_auth = 'sst:'; +SET GLOBAL wsrep_sst_method = 'mysqldump'; +CREATE TABLE ten (f1 INTEGER); +INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size = 1000; +START TRANSACTION; +INSERT INTO t1 (f2) SELECT REPEAT('x', 255) FROM ten AS a1, ten AS a2, ten AS a3; +UPDATE t1 SET f2 = REPEAT('y', 255); +Shutting down server ... +Starting server ... +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +UPDATE t1 SET f2 = REPEAT('z', 255); +COMMIT; +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SELECT COUNT(*) = 1000 FROM t1; +COUNT(*) = 1000 +1 +SELECT COUNT(*) = 1000 FROM t1 WHERE f2 = REPEAT('z', 255); +COUNT(*) = 1000 +1 +DROP TABLE t1; +DROP TABLE ten; +SET SESSION wsrep_trx_fragment_size=0; +CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query"); +DROP USER sst; +CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query"); +CALL mtr.add_suppression("InnoDB: Error: Table \"mysql\"\\.\"innodb_index_stats\" not found"); +CALL mtr.add_suppression("InnoDB: New log files created"); +CALL mtr.add_suppression("InnoDB: Creating foreign key constraint system tables"); +CALL mtr.add_suppression("Can't open and lock time zone table"); +CALL mtr.add_suppression("Can't open and lock privilege tables"); +CALL mtr.add_suppression("Info table is not ready to be used"); +CALL mtr.add_suppression("Native table .* has the wrong structure"); diff --git a/mysql-test/suite/galera_sr/r/galera_sr_parallel_apply.result b/mysql-test/suite/galera_sr/r/galera_sr_parallel_apply.result new file mode 100644 index 00000000000..d63418adabe --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_parallel_apply.result @@ -0,0 +1,26 @@ +SET GLOBAL wsrep_slave_threads = 5; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f2) VALUES (1); +INSERT INTO t1 (f2) VALUES (1); +INSERT INTO t1 (f2) VALUES (1); +INSERT INTO t1 (f2) VALUES (1); +INSERT INTO t1 (f2) VALUES (1);; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f2) VALUES (2); +INSERT INTO t1 (f2) VALUES (2); +INSERT INTO t1 (f2) VALUES (2); +INSERT INTO t1 (f2) VALUES (2); +INSERT INTO t1 (f2) VALUES (2);; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +COMMIT; +ROLLBACK; +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_rollback.result b/mysql-test/suite/galera_sr/r/galera_sr_rollback.result new file mode 100644 index 00000000000..c99dd3df549 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_rollback.result @@ -0,0 +1,29 @@ +CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1, 'a'); +INSERT INTO t1 VALUES (2, 'a'); +INSERT INTO t1 VALUES (3, 'a'); +INSERT INTO t1 VALUES (4, 'a'); +INSERT INTO t1 VALUES (5, 'a'); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +INSERT INTO t1 VALUES (11, 'b'); +INSERT INTO t1 VALUES (12, 'b'); +INSERT INTO t1 VALUES (13, 'b'); +INSERT INTO t1 VALUES (14, 'b'); +INSERT INTO t1 VALUES (15, 'b'); +ROLLBACK; +START TRANSACTION; +INSERT INTO t1 VALUES (1, 'a'); +INSERT INTO t1 VALUES (2, 'a'); +INSERT INTO t1 VALUES (3, 'a'); +INSERT INTO t1 VALUES (4, 'a'); +INSERT INTO t1 VALUES (5, 'a'); +INSERT INTO t1 VALUES (11, 'b'); +INSERT INTO t1 VALUES (12, 'b'); +INSERT INTO t1 VALUES (13, 'b'); +INSERT INTO t1 VALUES (14, 'b'); +INSERT INTO t1 VALUES (15, 'b'); +COMMIT; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_rollback_retry.result b/mysql-test/suite/galera_sr/r/galera_sr_rollback_retry.result new file mode 100644 index 00000000000..8af64da9a19 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_rollback_retry.result @@ -0,0 +1,26 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +ROLLBACK; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +COMMIT; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_rollback_savepoint.result b/mysql-test/suite/galera_sr/r/galera_sr_rollback_savepoint.result new file mode 100644 index 00000000000..d1b8985be82 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_rollback_savepoint.result @@ -0,0 +1,33 @@ +CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1, 'a'); +INSERT INTO t1 VALUES (2, 'a'); +INSERT INTO t1 VALUES (3, 'a'); +INSERT INTO t1 VALUES (4, 'a'); +INSERT INTO t1 VALUES (5, 'a'); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SAVEPOINT s1; +INSERT INTO t1 VALUES (11, 'b'); +INSERT INTO t1 VALUES (12, 'b'); +INSERT INTO t1 VALUES (13, 'b'); +INSERT INTO t1 VALUES (14, 'b'); +INSERT INTO t1 VALUES (15, 'b'); +ROLLBACK TO SAVEPOINT s1; +INSERT INTO t1 VALUES (21, 'c'); +INSERT INTO t1 VALUES (22, 'c'); +INSERT INTO t1 VALUES (23, 'c'); +INSERT INTO t1 VALUES (24, 'c'); +INSERT INTO t1 VALUES (25, 'c'); +SELECT COUNT(*) = 5 FROM t1 WHERE f2 = 'a'; +COUNT(*) = 5 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'b'; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 5 FROM t1 WHERE f2 = 'c'; +COUNT(*) = 5 +1 +COMMIT; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_rollback_statement.result b/mysql-test/suite/galera_sr/r/galera_sr_rollback_statement.result new file mode 100644 index 00000000000..21e6ef4b057 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_rollback_statement.result @@ -0,0 +1,22 @@ +CREATE TABLE ten (f1 INTEGER); +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) ENGINE=InnoDB; +INSERT INTO t1 (f2) SELECT REPEAT('a', 255) FROM ten AS a1, ten AS a2, ten AS a3; +ALTER TABLE t1 CHANGE f1 f1 INTEGER; +ALTER TABLE t1 DROP PRIMARY KEY; +INSERT INTO t1 VALUES (1, 'abc'); +SET SESSION wsrep_trx_fragment_size = 1; +INSERT INTO t2 SELECT * FROM t1; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +INSERT INTO t2 VALUES (1, 'abc'); +INSERT INTO t2 VALUES (2, 'abc'); +SELECT COUNT(*) = 2 FROM t2; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 2 FROM t2; +COUNT(*) = 2 +1 +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE ten; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_sbr.result b/mysql-test/suite/galera_sr/r/galera_sr_sbr.result new file mode 100644 index 00000000000..c83db3d5ea6 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_sbr.result @@ -0,0 +1,16 @@ +CREATE TABLE t1 (id INT) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET SESSION BINLOG_FORMAT='STATEMENT'; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +COMMIT; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_shutdown_master.result b/mysql-test/suite/galera_sr/r/galera_sr_shutdown_master.result new file mode 100644 index 00000000000..d3e1739af93 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_shutdown_master.result @@ -0,0 +1,20 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE = InnoDB; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES (1),(2),(3); +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +INSERT INTO t1 VALUES (1),(2),(3); +SELECT COUNT(*) = 3 FROM t1; +COUNT(*) = 3 +1 +DROP TABLE t1; +CALL mtr.add_suppression("WSREP: failed to send SR rollback for "); diff --git a/mysql-test/suite/galera_sr/r/galera_sr_shutdown_slave.result b/mysql-test/suite/galera_sr/r/galera_sr_shutdown_slave.result new file mode 100644 index 00000000000..98488dc773e --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_shutdown_slave.result @@ -0,0 +1,29 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE = InnoDB; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES (11),(12),(13); +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES (21),(22),(23); +INSERT INTO t1 VALUES (14),(15),(16); +COMMIT; +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 6 FROM t1 WHERE f1 IN (11,12,13,14,15,16); +COUNT(*) = 6 +1 +INSERT INTO t1 VALUES (24),(25),(26); +COMMIT; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 12 FROM t1; +COUNT(*) = 12 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_small_gcache.result b/mysql-test/suite/galera_sr/r/galera_sr_small_gcache.result new file mode 100644 index 00000000000..b1be41eb762 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_small_gcache.result @@ -0,0 +1,10 @@ +CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +SET SESSION wsrep_trx_fragment_size = 1; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; +SELECT COUNT(*) = 10000 FROM t1; +COUNT(*) = 10000 +1 +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_table_contents.result b/mysql-test/suite/galera_sr/r/galera_sr_table_contents.result new file mode 100644 index 00000000000..29bb71704e2 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_table_contents.result @@ -0,0 +1,198 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3); +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3); +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +Start of Simple Insert +INSERT INTO t1 VALUES (4); +DELIMITER /*!*/; +# at 120 +<ISO TIMESTAMP> server id 1 end_log_pos 73 Query thread_id=<QUERY_THREAD_ID> exec_time=<EXEC_TIME> error_code=0 +SET TIMESTAMP=<TIMESTAMP>/*!*/; +/*!\C latin1 *//*!*/; +BEGIN +/*!*/; +# at 193 +<ISO TIMESTAMP> server id 1 end_log_pos 114 Table_map: `test`.`t1` mapped to number <TABLE_ID> +# at 234 +<ISO TIMESTAMP> server id 1 end_log_pos 150 Write_rows: table id <TABLE_ID> flags: STMT_END_F +DELIMITER ; +# End of log file +ROLLBACK /* added by mysqlbinlog */; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +End of Simple Insert + +ROLLBACK; +Start of Multi-row Update +UPDATE t1 SET f1 = f1 + 10; +DELIMITER /*!*/; +# at 120 +<ISO TIMESTAMP> server id 1 end_log_pos 73 Query thread_id=<QUERY_THREAD_ID> exec_time=<EXEC_TIME> error_code=0 +SET TIMESTAMP=<TIMESTAMP>/*!*/; +/*!\C latin1 *//*!*/; +BEGIN +/*!*/; +# at 193 +<ISO TIMESTAMP> server id 1 end_log_pos 114 Table_map: `test`.`t1` mapped to number <TABLE_ID> +# at 234 +<ISO TIMESTAMP> server id 1 end_log_pos 156 Update_rows: table id <TABLE_ID> flags: STMT_END_F +DELIMITER ; +# End of log file +ROLLBACK /* added by mysqlbinlog */; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +DELIMITER /*!*/; +# at 120 +<ISO TIMESTAMP> server id 1 end_log_pos 197 Table_map: `test`.`t1` mapped to number <TABLE_ID> +# at 161 +<ISO TIMESTAMP> server id 1 end_log_pos 239 Update_rows: table id <TABLE_ID> flags: STMT_END_F +DELIMITER ; +# End of log file +ROLLBACK /* added by mysqlbinlog */; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +DELIMITER /*!*/; +# at 120 +<ISO TIMESTAMP> server id 1 end_log_pos 280 Table_map: `test`.`t1` mapped to number <TABLE_ID> +# at 161 +<ISO TIMESTAMP> server id 1 end_log_pos 322 Update_rows: table id <TABLE_ID> flags: STMT_END_F +DELIMITER ; +# End of log file +ROLLBACK /* added by mysqlbinlog */; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +End of Multi-row Update + +ROLLBACK; +Start of Multi-table Update +UPDATE t1, t2 SET t1.f1 = t1.f1 + 100, t2.f1 = t2.f1 + 100; +DELIMITER /*!*/; +# at 120 +<ISO TIMESTAMP> server id 1 end_log_pos 82 Query thread_id=<QUERY_THREAD_ID> exec_time=<EXEC_TIME> error_code=0 +SET TIMESTAMP=<TIMESTAMP>/*!*/; +/*!\C latin1 *//*!*/; +BEGIN +/*!*/; +# at 202 +<ISO TIMESTAMP> server id 1 end_log_pos 123 Table_map: `test`.`t1` mapped to number <TABLE_ID> +# at 243 +<ISO TIMESTAMP> server id 1 end_log_pos 164 Table_map: `test`.`t2` mapped to number <TABLE_ID> +# at 284 +<ISO TIMESTAMP> server id 1 end_log_pos 206 Update_rows: table id <TABLE_ID> flags: STMT_END_F +DELIMITER ; +# End of log file +ROLLBACK /* added by mysqlbinlog */; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +DELIMITER /*!*/; +# at 120 +<ISO TIMESTAMP> server id 1 end_log_pos 247 Table_map: `test`.`t1` mapped to number <TABLE_ID> +# at 161 +<ISO TIMESTAMP> server id 1 end_log_pos 288 Table_map: `test`.`t2` mapped to number <TABLE_ID> +# at 202 +<ISO TIMESTAMP> server id 1 end_log_pos 330 Update_rows: table id <TABLE_ID> flags: STMT_END_F +DELIMITER ; +# End of log file +ROLLBACK /* added by mysqlbinlog */; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +DELIMITER /*!*/; +# at 120 +<ISO TIMESTAMP> server id 1 end_log_pos 371 Table_map: `test`.`t1` mapped to number <TABLE_ID> +# at 161 +<ISO TIMESTAMP> server id 1 end_log_pos 412 Table_map: `test`.`t2` mapped to number <TABLE_ID> +# at 202 +<ISO TIMESTAMP> server id 1 end_log_pos 454 Update_rows: table id <TABLE_ID> flags: STMT_END_F +DELIMITER ; +# End of log file +ROLLBACK /* added by mysqlbinlog */; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +DELIMITER /*!*/; +# at 120 +<ISO TIMESTAMP> server id 1 end_log_pos 495 Table_map: `test`.`t1` mapped to number <TABLE_ID> +# at 161 +<ISO TIMESTAMP> server id 1 end_log_pos 536 Table_map: `test`.`t2` mapped to number <TABLE_ID> +# at 202 +<ISO TIMESTAMP> server id 1 end_log_pos 578 Update_rows: table id <TABLE_ID> flags: STMT_END_F +DELIMITER ; +# End of log file +ROLLBACK /* added by mysqlbinlog */; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +DELIMITER /*!*/; +# at 120 +<ISO TIMESTAMP> server id 1 end_log_pos 619 Table_map: `test`.`t1` mapped to number <TABLE_ID> +# at 161 +<ISO TIMESTAMP> server id 1 end_log_pos 660 Table_map: `test`.`t2` mapped to number <TABLE_ID> +# at 202 +<ISO TIMESTAMP> server id 1 end_log_pos 702 Update_rows: table id <TABLE_ID> flags: STMT_END_F +DELIMITER ; +# End of log file +ROLLBACK /* added by mysqlbinlog */; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +DELIMITER /*!*/; +# at 120 +<ISO TIMESTAMP> server id 1 end_log_pos 743 Table_map: `test`.`t1` mapped to number <TABLE_ID> +# at 161 +<ISO TIMESTAMP> server id 1 end_log_pos 784 Table_map: `test`.`t2` mapped to number <TABLE_ID> +# at 202 +<ISO TIMESTAMP> server id 1 end_log_pos 826 Update_rows: table id <TABLE_ID> flags: STMT_END_F +DELIMITER ; +# End of log file +ROLLBACK /* added by mysqlbinlog */; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +End of Multi-table Update + +ROLLBACK; +Start of Savepoint +INSERT INTO t1 VALUES (1000); +SAVEPOINT X; +INSERT INTO t1 VALUES (2000); +ROLLBACK TO SAVEPOINT X; +DELIMITER /*!*/; +# at 120 +<ISO TIMESTAMP> server id 1 end_log_pos 73 Query thread_id=<QUERY_THREAD_ID> exec_time=<EXEC_TIME> error_code=0 +SET TIMESTAMP=<TIMESTAMP>/*!*/; +/*!\C latin1 *//*!*/; +BEGIN +/*!*/; +# at 193 +<ISO TIMESTAMP> server id 1 end_log_pos 114 Table_map: `test`.`t1` mapped to number <TABLE_ID> +# at 234 +<ISO TIMESTAMP> server id 1 end_log_pos 150 Write_rows: table id <TABLE_ID> flags: STMT_END_F +DELIMITER ; +# End of log file +ROLLBACK /* added by mysqlbinlog */; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +DELIMITER /*!*/; +# at 120 +<ISO TIMESTAMP> server id 1 end_log_pos 231 Query thread_id=<QUERY_THREAD_ID> exec_time=<EXEC_TIME> error_code=0 +SET TIMESTAMP=<TIMESTAMP>/*!*/; +/*!\C latin1 *//*!*/; +SAVEPOINT `X` +/*!*/; +DELIMITER ; +# End of log file +ROLLBACK /* added by mysqlbinlog */; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +DELIMITER /*!*/; +# at 120 +<ISO TIMESTAMP> server id 1 end_log_pos 272 Table_map: `test`.`t1` mapped to number <TABLE_ID> +# at 161 +<ISO TIMESTAMP> server id 1 end_log_pos 308 Write_rows: table id <TABLE_ID> flags: STMT_END_F +DELIMITER ; +# End of log file +ROLLBACK /* added by mysqlbinlog */; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +DELIMITER /*!*/; +# at 120 +<ISO TIMESTAMP> server id 1 end_log_pos 391 Query thread_id=<QUERY_THREAD_ID> exec_time=<EXEC_TIME> error_code=0 +SET TIMESTAMP=<TIMESTAMP>/*!*/; +/*!\C latin1 *//*!*/; +ROLLBACK TO `X` +/*!*/; +DELIMITER ; +# End of log file +ROLLBACK /* added by mysqlbinlog */; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +End of Savepoint + +ROLLBACK; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_transaction_replay.result b/mysql-test/suite/galera_sr/r/galera_sr_transaction_replay.result new file mode 100644 index 00000000000..7527b4ede31 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_transaction_replay.result @@ -0,0 +1,101 @@ +SET SESSION wsrep_sync_wait = 0; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)); +INSERT INTO t1 VALUES (1, 'a'); +INSERT INTO t1 VALUES (2, 'a'); +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 1; +START TRANSACTION; +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE; +f1 f2 +2 a +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +UPDATE t1 SET f2 = 'c' WHERE f1 = 2; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync'; +COMMIT; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync'; +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +wsrep_local_replays +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DELETE FROM t1; +INSERT INTO t1 VALUES (1, 'a'); +INSERT INTO t1 VALUES (2, 'a'); +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 1; +START TRANSACTION; +UPDATE t1 SET f2 = 'x' WHERE f1 = 1; +SET SESSION wsrep_trx_fragment_size = 0; +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE; +f1 f2 +2 a +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +UPDATE t1 SET f2 = 'c' WHERE f1 = 2; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_master_enter_sync'; +COMMIT; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync'; +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +wsrep_local_replays +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DELETE FROM t1; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_unit_statements.result b/mysql-test/suite/galera_sr/r/galera_sr_unit_statements.result new file mode 100644 index 00000000000..0a81812f7c0 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_unit_statements.result @@ -0,0 +1,18 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 3; +SET SESSION wsrep_trx_fragment_unit = 'statements'; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +INSERT INTO t1 VALUES (6); +COMMIT; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_v1_row_events.result b/mysql-test/suite/galera_sr/r/galera_sr_v1_row_events.result new file mode 100644 index 00000000000..2987430b9e1 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_v1_row_events.result @@ -0,0 +1,15 @@ +CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +COMMIT; +SET AUTOCOMMIT=ON; +UPDATE t1 SET f1 = 2 WHERE f1 = 1; +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_ws_size.result b/mysql-test/suite/galera_sr/r/galera_sr_ws_size.result new file mode 100644 index 00000000000..bbd1f8c9585 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_ws_size.result @@ -0,0 +1,29 @@ +CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(254)) ENGINE=InnoDB; +CREATE TABLE ten (f1 INTEGER); +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +SET SESSION wsrep_trx_fragment_size = 512; +SET GLOBAL wsrep_provider_options='repl.max_ws_size=4096'; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1; +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1; +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1; +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1; +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1; +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1; +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1; +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1; +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1; +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +COMMIT; +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +SELECT COUNT(*) = 100 FROM t1; +COUNT(*) = 100 +1 +DROP TABLE t1; +DROP TABLE ten; +call mtr.add_suppression('WSREP: transaction size limit.*'); +call mtr.add_suppression('WSREP: rbr write fail.*'); +call mtr.add_suppression('WSREP: Maximum writeset size exceeded by.*'); +call mtr.add_suppression('WSREP: transaction size exceeded.*'); diff --git a/mysql-test/suite/galera_sr/r/galera_sr_ws_size2.result b/mysql-test/suite/galera_sr/r/galera_sr_ws_size2.result new file mode 100644 index 00000000000..e1a15b591ef --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_ws_size2.result @@ -0,0 +1,28 @@ +CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(254)) ENGINE=InnoDB; +CREATE TABLE ten (f1 INTEGER); +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +SET SESSION wsrep_trx_fragment_size = 256; +SET GLOBAL wsrep_provider_options='repl.max_ws_size=128'; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1, ten AS a2; +Got one of the listed errors +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +DROP TABLE t1; +DROP TABLE ten; +call mtr.add_suppression('WSREP: SR rollback replication failure.*'); +call mtr.add_suppression('WSREP: transaction size limit.*'); +call mtr.add_suppression('WSREP: SR rbr write fail.*'); +call mtr.add_suppression('WSREP: Maximum writeset size exceeded by.*'); +call mtr.add_suppression('WSREP: transaction size exceeded.*'); +call mtr.add_suppression('WSREP: fragment replication failed:'); +call mtr.add_suppression('WSREP: post commit failed for SR rollback'); +call mtr.add_suppression('WSREP: pre_commit for SR rollback returned 2, thd:*'); +call mtr.add_suppression('WSREP: wsrep_rollback failed to send SR ROLLBACK for *'); diff --git a/mysql-test/suite/galera_sr/r/galera_var_ignore_apply_errors_sr.result b/mysql-test/suite/galera_sr/r/galera_var_ignore_apply_errors_sr.result new file mode 100644 index 00000000000..97c32d7c00e --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_var_ignore_apply_errors_sr.result @@ -0,0 +1,22 @@ +SET GLOBAL wsrep_ignore_apply_errors = 2; +CREATE TABLE t1 (f1 INTEGER); +INSERT INTO t1 VALUES (2); +SET GLOBAL wsrep_on = OFF; +INSERT INTO t1 VALUES (1); +SET GLOBAL wsrep_on = ON; +SET SESSION wsrep_trx_fragment_size = 1; +START TRANSACTION; +INSERT INTO t1 VALUES (3); +DELETE FROM t1 WHERE f1 = 1; +DELETE FROM t1 WHERE f1 = 2; +COMMIT; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SET SESSION wsrep_trx_fragment_size = 0; +DROP TABLE t1; +SET GLOBAL wsrep_ignore_apply_errors = 7; +CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows event"); diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep#215.result b/mysql-test/suite/galera_sr/r/mysql-wsrep#215.result new file mode 100644 index 00000000000..84564cabe6b --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep#215.result @@ -0,0 +1,88 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 2; +SET SESSION wsrep_trx_fragment_unit = 'statements'; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +SET GLOBAL debug = 'd,sync.wsrep_apply_cb'; +SET SESSION wsrep_sync_wait = 0; +INSERT INTO t1 VALUES (1); +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +INSERT INTO t1 VALUES (1); +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; +SET GLOBAL debug = ''; +INSERT INTO t1 VALUES (2); +Got one of the listed errors +COMMIT; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +TRUNCATE TABLE t1; +SET SESSION wsrep_trx_fragment_size = 10; +SET SESSION wsrep_trx_fragment_unit = 'bytes'; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +SET GLOBAL debug = 'd,sync.wsrep_apply_cb'; +SET SESSION wsrep_sync_wait = 0; +INSERT INTO t1 VALUES (1); +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +INSERT INTO t1 VALUES (1); +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; +SET GLOBAL debug = ''; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +INSERT INTO t1 VALUES (2); +COMMIT; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 2 FROM t1; +COUNT(*) = 2 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +TRUNCATE TABLE t1; +SET SESSION wsrep_trx_fragment_size = 200; +SET SESSION wsrep_trx_fragment_unit = 'bytes'; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +SET GLOBAL debug = 'd,sync.wsrep_apply_cb'; +SET SESSION wsrep_sync_wait = 0; +INSERT INTO t1 VALUES (1); +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; +SET GLOBAL debug = ''; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +COMMIT; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#136.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#136.result new file mode 100644 index 00000000000..7039af8fd64 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#136.result @@ -0,0 +1,41 @@ +RESET MASTER; +RESET MASTER; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +COMMIT; +SET SESSION wsrep_trx_fragment_size = 0; +INSERT INTO t1 VALUES (3),(4); +COMMIT; +SHOW BINLOG EVENTS IN '0.000001' FROM 120; +Log_name Pos Event_type Server_id End_log_pos Info +0.000001 <Pos> Query 1 <End_log_pos> use `test`; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB +0.000001 <Pos> Query 1 <End_log_pos> BEGIN +0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1) +0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1) +0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */ +0.000001 <Pos> Query 1 <End_log_pos> BEGIN +0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1) +0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */ +SELECT COUNT(*) = 4 FROM t1; +COUNT(*) = 4 +1 +SHOW BINLOG EVENTS IN '0.000001' FROM 120; +Log_name Pos Event_type Server_id End_log_pos Info +0.000001 <Pos> Query 1 <End_log_pos> use `test`; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB +0.000001 <Pos> Query 1 <End_log_pos> BEGIN +0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1) +0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1) +0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */ +0.000001 <Pos> Query 1 <End_log_pos> BEGIN +0.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1) +0.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F +0.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */ +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#138.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#138.result new file mode 100644 index 00000000000..efe056b92b4 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#138.result @@ -0,0 +1,17 @@ +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +SELECT flags FROM wsrep_schema.SR; +flags +64 +0 +ROLLBACK; +INSERT INTO t1 VALUES (3),(4); +SELECT flags FROM wsrep_schema.SR; +flags +64 +0 +ROLLBACK; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#14.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#14.result new file mode 100644 index 00000000000..9e122f554b2 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#14.result @@ -0,0 +1,8 @@ +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +COMMIT; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#148.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#148.result new file mode 100644 index 00000000000..65d1a2e1ec0 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#148.result @@ -0,0 +1,27 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t2 VALUES (6),(7),(8),(9),(10),(1); +SET GLOBAL wsrep_slave_threads = 2; +SET GLOBAL DEBUG = 'd,sync.wsrep_apply_cb'; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1), (2), (3), (4), (5); +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1), (2), (3), (4), (5);; +INSERT INTO t1 SELECT * FROM t2;; +INSERT INTO t1 VALUES (6), (7), (8), (9), (10); +COMMIT; +Got one of the listed errors +SET GLOBAL wsrep_slave_threads = 1; +SET GLOBAL DEBUG = ''; +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; +SELECT COUNT(*) = 10 FROM t1; +COUNT(*) = 10 +1 +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#15.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#15.result new file mode 100644 index 00000000000..5f50f7fd9a7 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#15.result @@ -0,0 +1,8 @@ +CREATE TABLE t1 (id INT) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +COMMIT; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#165.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#165.result new file mode 100644 index 00000000000..fe0761d186d --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#165.result @@ -0,0 +1,752 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x'); +START TRANSACTION; +UPDATE t1 SET f2 = 'a' WHERE f1 = 1; +UPDATE t1 SET f2 = 'a' WHERE f1 = 4; +UPDATE t1 SET f2 = 'a' WHERE f1 = 5; +START TRANSACTION; +SET SESSION wsrep_trx_fragment_size = 1; +INSERT INTO t1 VALUES (3, 'b'); +UPDATE t1 SET f2 = 'b' WHERE f1 = 2; +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (3, 'c'); +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +UPDATE t1 SET f2 = 'a' WHERE f1 = 2; +SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue'; +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SET DEBUG_SYNC = 'now WAIT_FOR wait'; +SET DEBUG_SYNC = 'now SIGNAL continue'; +UPDATE t1 SET f2 = 'x' WHERE f1 = 3; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x'); +START TRANSACTION; +UPDATE t1 SET f2 = 'a' WHERE f1 = 1; +UPDATE t1 SET f2 = 'a' WHERE f1 = 4; +UPDATE t1 SET f2 = 'a' WHERE f1 = 5; +START TRANSACTION; +SET SESSION wsrep_trx_fragment_size = 1; +INSERT INTO t1 VALUES (3, 'b'); +UPDATE t1 SET f2 = 'b' WHERE f1 = 2; +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (3, 'c'); +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +UPDATE t1 SET f2 = 'a' WHERE f1 = 2; +SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue'; +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SET DEBUG_SYNC = 'now WAIT_FOR wait'; +SET DEBUG_SYNC = 'now SIGNAL continue'; +UPDATE t1 SET f2 = 'x' WHERE f1 = 3; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x'); +START TRANSACTION; +UPDATE t1 SET f2 = 'a' WHERE f1 = 1; +UPDATE t1 SET f2 = 'a' WHERE f1 = 4; +UPDATE t1 SET f2 = 'a' WHERE f1 = 5; +START TRANSACTION; +SET SESSION wsrep_trx_fragment_size = 1; +INSERT INTO t1 VALUES (3, 'b'); +UPDATE t1 SET f2 = 'b' WHERE f1 = 2; +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (3, 'c'); +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +UPDATE t1 SET f2 = 'a' WHERE f1 = 2; +SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue'; +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SET DEBUG_SYNC = 'now WAIT_FOR wait'; +SET DEBUG_SYNC = 'now SIGNAL continue'; +UPDATE t1 SET f2 = 'x' WHERE f1 = 3; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x'); +START TRANSACTION; +UPDATE t1 SET f2 = 'a' WHERE f1 = 1; +UPDATE t1 SET f2 = 'a' WHERE f1 = 4; +UPDATE t1 SET f2 = 'a' WHERE f1 = 5; +START TRANSACTION; +SET SESSION wsrep_trx_fragment_size = 1; +INSERT INTO t1 VALUES (3, 'b'); +UPDATE t1 SET f2 = 'b' WHERE f1 = 2; +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (3, 'c'); +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +UPDATE t1 SET f2 = 'a' WHERE f1 = 2; +SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue'; +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SET DEBUG_SYNC = 'now WAIT_FOR wait'; +SET DEBUG_SYNC = 'now SIGNAL continue'; +UPDATE t1 SET f2 = 'x' WHERE f1 = 3; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x'); +START TRANSACTION; +UPDATE t1 SET f2 = 'a' WHERE f1 = 1; +UPDATE t1 SET f2 = 'a' WHERE f1 = 4; +UPDATE t1 SET f2 = 'a' WHERE f1 = 5; +START TRANSACTION; +SET SESSION wsrep_trx_fragment_size = 1; +INSERT INTO t1 VALUES (3, 'b'); +UPDATE t1 SET f2 = 'b' WHERE f1 = 2; +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (3, 'c'); +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +UPDATE t1 SET f2 = 'a' WHERE f1 = 2; +SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue'; +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SET DEBUG_SYNC = 'now WAIT_FOR wait'; +SET DEBUG_SYNC = 'now SIGNAL continue'; +UPDATE t1 SET f2 = 'x' WHERE f1 = 3; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x'); +START TRANSACTION; +UPDATE t1 SET f2 = 'a' WHERE f1 = 1; +UPDATE t1 SET f2 = 'a' WHERE f1 = 4; +UPDATE t1 SET f2 = 'a' WHERE f1 = 5; +START TRANSACTION; +SET SESSION wsrep_trx_fragment_size = 1; +INSERT INTO t1 VALUES (3, 'b'); +UPDATE t1 SET f2 = 'b' WHERE f1 = 2; +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (3, 'c'); +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +UPDATE t1 SET f2 = 'a' WHERE f1 = 2; +SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue'; +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SET DEBUG_SYNC = 'now WAIT_FOR wait'; +SET DEBUG_SYNC = 'now SIGNAL continue'; +UPDATE t1 SET f2 = 'x' WHERE f1 = 3; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x'); +START TRANSACTION; +UPDATE t1 SET f2 = 'a' WHERE f1 = 1; +UPDATE t1 SET f2 = 'a' WHERE f1 = 4; +UPDATE t1 SET f2 = 'a' WHERE f1 = 5; +START TRANSACTION; +SET SESSION wsrep_trx_fragment_size = 1; +INSERT INTO t1 VALUES (3, 'b'); +UPDATE t1 SET f2 = 'b' WHERE f1 = 2; +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (3, 'c'); +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +UPDATE t1 SET f2 = 'a' WHERE f1 = 2; +SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue'; +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SET DEBUG_SYNC = 'now WAIT_FOR wait'; +SET DEBUG_SYNC = 'now SIGNAL continue'; +UPDATE t1 SET f2 = 'x' WHERE f1 = 3; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x'); +START TRANSACTION; +UPDATE t1 SET f2 = 'a' WHERE f1 = 1; +UPDATE t1 SET f2 = 'a' WHERE f1 = 4; +UPDATE t1 SET f2 = 'a' WHERE f1 = 5; +START TRANSACTION; +SET SESSION wsrep_trx_fragment_size = 1; +INSERT INTO t1 VALUES (3, 'b'); +UPDATE t1 SET f2 = 'b' WHERE f1 = 2; +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (3, 'c'); +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +UPDATE t1 SET f2 = 'a' WHERE f1 = 2; +SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue'; +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SET DEBUG_SYNC = 'now WAIT_FOR wait'; +SET DEBUG_SYNC = 'now SIGNAL continue'; +UPDATE t1 SET f2 = 'x' WHERE f1 = 3; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x'); +START TRANSACTION; +UPDATE t1 SET f2 = 'a' WHERE f1 = 1; +UPDATE t1 SET f2 = 'a' WHERE f1 = 4; +UPDATE t1 SET f2 = 'a' WHERE f1 = 5; +START TRANSACTION; +SET SESSION wsrep_trx_fragment_size = 1; +INSERT INTO t1 VALUES (3, 'b'); +UPDATE t1 SET f2 = 'b' WHERE f1 = 2; +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (3, 'c'); +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +UPDATE t1 SET f2 = 'a' WHERE f1 = 2; +SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue'; +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SET DEBUG_SYNC = 'now WAIT_FOR wait'; +SET DEBUG_SYNC = 'now SIGNAL continue'; +UPDATE t1 SET f2 = 'x' WHERE f1 = 3; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x'); +START TRANSACTION; +UPDATE t1 SET f2 = 'a' WHERE f1 = 1; +UPDATE t1 SET f2 = 'a' WHERE f1 = 4; +UPDATE t1 SET f2 = 'a' WHERE f1 = 5; +START TRANSACTION; +SET SESSION wsrep_trx_fragment_size = 1; +INSERT INTO t1 VALUES (3, 'b'); +UPDATE t1 SET f2 = 'b' WHERE f1 = 2; +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (3, 'c'); +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +UPDATE t1 SET f2 = 'a' WHERE f1 = 2; +SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue'; +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SET DEBUG_SYNC = 'now WAIT_FOR wait'; +SET DEBUG_SYNC = 'now SIGNAL continue'; +UPDATE t1 SET f2 = 'x' WHERE f1 = 3; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x'); +START TRANSACTION; +UPDATE t1 SET f2 = 'a' WHERE f1 = 1; +UPDATE t1 SET f2 = 'a' WHERE f1 = 4; +UPDATE t1 SET f2 = 'a' WHERE f1 = 5; +START TRANSACTION; +SET SESSION wsrep_trx_fragment_size = 1; +INSERT INTO t1 VALUES (3, 'b'); +UPDATE t1 SET f2 = 'b' WHERE f1 = 2; +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (3, 'c'); +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +UPDATE t1 SET f2 = 'a' WHERE f1 = 2; +SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue'; +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SET DEBUG_SYNC = 'now WAIT_FOR wait'; +SET DEBUG_SYNC = 'now SIGNAL continue'; +UPDATE t1 SET f2 = 'x' WHERE f1 = 3; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x'); +START TRANSACTION; +UPDATE t1 SET f2 = 'a' WHERE f1 = 1; +UPDATE t1 SET f2 = 'a' WHERE f1 = 4; +UPDATE t1 SET f2 = 'a' WHERE f1 = 5; +START TRANSACTION; +SET SESSION wsrep_trx_fragment_size = 1; +INSERT INTO t1 VALUES (3, 'b'); +UPDATE t1 SET f2 = 'b' WHERE f1 = 2; +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (3, 'c'); +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +UPDATE t1 SET f2 = 'a' WHERE f1 = 2; +SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue'; +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SET DEBUG_SYNC = 'now WAIT_FOR wait'; +SET DEBUG_SYNC = 'now SIGNAL continue'; +UPDATE t1 SET f2 = 'x' WHERE f1 = 3; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x'); +START TRANSACTION; +UPDATE t1 SET f2 = 'a' WHERE f1 = 1; +UPDATE t1 SET f2 = 'a' WHERE f1 = 4; +UPDATE t1 SET f2 = 'a' WHERE f1 = 5; +START TRANSACTION; +SET SESSION wsrep_trx_fragment_size = 1; +INSERT INTO t1 VALUES (3, 'b'); +UPDATE t1 SET f2 = 'b' WHERE f1 = 2; +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (3, 'c'); +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +UPDATE t1 SET f2 = 'a' WHERE f1 = 2; +SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue'; +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SET DEBUG_SYNC = 'now WAIT_FOR wait'; +SET DEBUG_SYNC = 'now SIGNAL continue'; +UPDATE t1 SET f2 = 'x' WHERE f1 = 3; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x'); +START TRANSACTION; +UPDATE t1 SET f2 = 'a' WHERE f1 = 1; +UPDATE t1 SET f2 = 'a' WHERE f1 = 4; +UPDATE t1 SET f2 = 'a' WHERE f1 = 5; +START TRANSACTION; +SET SESSION wsrep_trx_fragment_size = 1; +INSERT INTO t1 VALUES (3, 'b'); +UPDATE t1 SET f2 = 'b' WHERE f1 = 2; +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (3, 'c'); +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +UPDATE t1 SET f2 = 'a' WHERE f1 = 2; +SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue'; +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SET DEBUG_SYNC = 'now WAIT_FOR wait'; +SET DEBUG_SYNC = 'now SIGNAL continue'; +UPDATE t1 SET f2 = 'x' WHERE f1 = 3; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x'); +START TRANSACTION; +UPDATE t1 SET f2 = 'a' WHERE f1 = 1; +UPDATE t1 SET f2 = 'a' WHERE f1 = 4; +UPDATE t1 SET f2 = 'a' WHERE f1 = 5; +START TRANSACTION; +SET SESSION wsrep_trx_fragment_size = 1; +INSERT INTO t1 VALUES (3, 'b'); +UPDATE t1 SET f2 = 'b' WHERE f1 = 2; +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (3, 'c'); +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +UPDATE t1 SET f2 = 'a' WHERE f1 = 2; +SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue'; +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SET DEBUG_SYNC = 'now WAIT_FOR wait'; +SET DEBUG_SYNC = 'now SIGNAL continue'; +UPDATE t1 SET f2 = 'x' WHERE f1 = 3; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +DROP TABLE t1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x'); +START TRANSACTION; +UPDATE t1 SET f2 = 'a' WHERE f1 = 1; +UPDATE t1 SET f2 = 'a' WHERE f1 = 4; +UPDATE t1 SET f2 = 'a' WHERE f1 = 5; +START TRANSACTION; +SET SESSION wsrep_trx_fragment_size = 1; +INSERT INTO t1 VALUES (3, 'b'); +UPDATE t1 SET f2 = 'b' WHERE f1 = 2; +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (3, 'c'); +SELECT * FROM t1; +f1 f2 +1 x +2 x +4 x +5 x +UPDATE t1 SET f2 = 'a' WHERE f1 = 2; +SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue'; +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SET DEBUG_SYNC = 'now WAIT_FOR wait'; +SET DEBUG_SYNC = 'now SIGNAL continue'; +UPDATE t1 SET f2 = 'x' WHERE f1 = 3; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +SELECT * FROM t1; +f1 f2 +1 a +2 a +3 x +4 a +5 a +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#213.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#213.result new file mode 100644 index 00000000000..1cbd9c3d1b7 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#213.result @@ -0,0 +1,26 @@ +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +SET GLOBAL wsrep_cluster_address = ''; +INSERT INTO t1 VALUES (6); +ERROR HY000: Lost connection to MySQL server during query +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; +CALL mtr.add_suppression("WSREP: failed to send SR rollback for "); diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#214.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#214.result new file mode 100644 index 00000000000..efc86106ab1 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#214.result @@ -0,0 +1,46 @@ +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +SET GLOBAL wsrep_cluster_address = ''; +INSERT INTO t1 VALUES (6); +INSERT INTO t1 VALUES (7); +INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (9); +INSERT INTO t1 VALUES (10); +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +COUNT(*) > 0 +1 +SELECT count(*) > 0 FROM wsrep_schema.SR; +count(*) > 0 +1 +INSERT INTO t1 VALUES (11); +INSERT INTO t1 VALUES (12); +INSERT INTO t1 VALUES (13); +INSERT INTO t1 VALUES (14); +INSERT INTO t1 VALUES (15); +COMMIT; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#22.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#22.result new file mode 100644 index 00000000000..a8cf599aacd --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#22.result @@ -0,0 +1,26 @@ +CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES (1, 'a'); +INSERT INTO t1 VALUES (2, 'a'); +INSERT INTO t1 VALUES (3, 'a'); +INSERT INTO t1 VALUES (4, 'a'); +INSERT INTO t1 VALUES (5, 'a'); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SAVEPOINT s1; +INSERT INTO t1 VALUES (11, 'b'); +INSERT INTO t1 VALUES (12, 'b'); +INSERT INTO t1 VALUES (13, 'b'); +INSERT INTO t1 VALUES (14, 'b'); +INSERT INTO t1 VALUES (15, 'b'); +ROLLBACK TO SAVEPOINT s1; +INSERT INTO t1 VALUES (21, 'c'); +COMMIT; +SELECT COUNT(*) = 6 FROM t1; +COUNT(*) = 6 +1 +SELECT COUNT(*) = 6 FROM t1; +COUNT(*) = 6 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#27.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#27.result new file mode 100644 index 00000000000..e92fc207895 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#27.result @@ -0,0 +1,17 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +SET SESSION wsrep_sync_wait = 0; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#29.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#29.result new file mode 100644 index 00000000000..29b17ea07d6 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#29.result @@ -0,0 +1,14 @@ +SET SESSION wsrep_trx_fragment_size = 1; +SET SESSION binlog_format = STATEMENT; +create table t1 (id int not null, f_id int not null, f int not null, +primary key(f_id, id)) engine=innodb; +create table t2 (id int not null,s_id int not null,s varchar(200), +primary key(id)) engine=innodb; +INSERT INTO t1 VALUES (8, 1, 3); +INSERT INTO t1 VALUES (1, 2, 1); +INSERT INTO t2 VALUES (1, 0, ''); +INSERT INTO t2 VALUES (8, 1, ''); +DELETE ml.* FROM t1 AS ml LEFT JOIN t2 AS mm ON (mm.id=ml.id) +WHERE mm.id IS NULL; +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#32.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#32.result new file mode 100644 index 00000000000..6e62108f23a --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#32.result @@ -0,0 +1,22 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SET AUTOCOMMIT=OFF; +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +START TRANSACTION; +INSERT INTO t1 VALUES (9); +INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (7); +INSERT INTO t1 VALUES (6); +INSERT INTO t1 VALUES (5); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +ROLLBACK; +COMMIT; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#35.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#35.result new file mode 100644 index 00000000000..7eeb83bdc5c --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#35.result @@ -0,0 +1,26 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SET SESSION wsrep_sync_wait = 0; +SET GLOBAL debug = 'd,sync.wsrep_apply_cb'; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SET SESSION wsrep_sync_wait = 0; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +INSERT INTO t1 VALUES (1);; +COMMIT; +SET GLOBAL debug = ''; +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; +Got one of the listed errors +ROLLBACK; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#8.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#8.result new file mode 100644 index 00000000000..a959589d241 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#8.result @@ -0,0 +1,27 @@ +SET SESSION wsrep_trx_fragment_size = 1; +CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); +CREATE TABLE t1 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(100), FULLTEXT (f2)) ENGINE=InnoDB; +SELECT COUNT(*) = 13 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE name LIKE 'test/%'; +COUNT(*) = 13 +1 +INSERT INTO t1 (f2) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; +SELECT COUNT(f2) = 10000 FROM t1 WHERE MATCH(f2) AGAINST ('foobarbaz'); +COUNT(f2) = 10000 +1 +UPDATE t1 SET f2 = 'abcdefjhk'; +SELECT COUNT(f2) = 10000 FROM t1 WHERE MATCH(f2) AGAINST ('abcdefjhk'); +COUNT(f2) = 10000 +1 +DROP TABLE t1; +CREATE TABLE t1 (f1 VARCHAR(100), FULLTEXT (f1)) ENGINE=InnoDB; +INSERT INTO t1 (f1) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3; +SELECT COUNT(f1) = 1000 FROM t1 WHERE MATCH(f1) AGAINST ('foobarbaz'); +COUNT(f1) = 1000 +1 +UPDATE t1 SET f1 = 'abcdefjhk'; +SELECT COUNT(f1) = 1000 FROM t1 WHERE MATCH(f1) AGAINST ('abcdefjhk'); +COUNT(f1) = 1000 +1 +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#9.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#9.result new file mode 100644 index 00000000000..694b51a9260 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#9.result @@ -0,0 +1,12 @@ +SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; +SET SESSION wsrep_trx_fragment_size = 1; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +Killing server ... +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='t1'; +COUNT(*) = 2 +1 +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +VARIABLE_VALUE = 2 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#93.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#93.result new file mode 100644 index 00000000000..1287af618c1 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#93.result @@ -0,0 +1,15 @@ +CREATE TABLE t1 (f1 INTEGER); +SET SESSION WSREP_TRX_FRAGMENT_SIZE=1; +START TRANSACTION; +SAVEPOINT a; +INSERT INTO t1 VALUES (1); +ROLLBACK TO SAVEPOINT a; +INSERT INTO t1 values (2); +COMMIT; +SELECT COUNT(*) = 0 from wsrep_schema.SR; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 from wsrep_schema.SR; +COUNT(*) = 0 +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-features#96.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#96.result new file mode 100644 index 00000000000..fa79196a910 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#96.result @@ -0,0 +1,26 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY); +CREATE TABLE t2 (f2 VARCHAR(32)); +SET SESSION wsrep_trx_fragment_size=1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2),(1); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +INSERT INTO t2 VALUES ('abc'); +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 1 FROM t2; +COUNT(*) = 1 +1 +ROLLBACK; +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t2; +COUNT(*) = 0 +1 +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera_sr/t/GCF-1008.inc b/mysql-test/suite/galera_sr/t/GCF-1008.inc new file mode 100644 index 00000000000..69245b3a91f --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-1008.inc @@ -0,0 +1,36 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) ENGINE=InnoDB; + +--connection node_2 +SET SESSION wsrep_trx_fragment_size = 1; +START TRANSACTION; +INSERT INTO t1 VALUES (1, 'x'); + +--connection node_2a +--source include/galera_set_sync_point.inc + +--connection node_2 +--send COMMIT + +--connection node_2b +--sleep 1 +SET SESSION wsrep_sync_wait = 0; +SELECT COUNT(*) = 0 FROM t1; + +--connection node_1 +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_trx_fragment_size = 1; +SELECT COUNT(*) = 1 FROM t1; +REPLACE INTO t1 VALUES (1,'y'); + +--connection node_2b +SELECT COUNT(*) = 0 FROM t1; + +--connection node_2a +--source include/galera_signal_sync_point.inc +--source include/galera_clear_sync_point.inc + +--connection node_2 +--reap +SELECT COUNT(*) = 1 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/GCF-1008.test b/mysql-test/suite/galera_sr/t/GCF-1008.test new file mode 100644 index 00000000000..c6926840bd1 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-1008.test @@ -0,0 +1,18 @@ +# +# GCF-1008 SR trx fails to apply because previous trx is not committed yet on applier +# + +--source include/have_debug_sync.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/galera_have_debug_sync.inc + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2 + +--let $galera_sync_point = before_local_commit_monitor_enter +--source GCF-1008.inc + +--let $galera_sync_point = before_certify_apply_monitor_enter +--source GCF-1008.inc + diff --git a/mysql-test/suite/galera_sr/t/GCF-1018.test b/mysql-test/suite/galera_sr/t/GCF-1018.test new file mode 100644 index 00000000000..1ff8f81e824 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-1018.test @@ -0,0 +1,38 @@ +# +# SR: Node hang with one thread waiting in InnoDB +# +--source include/have_debug_sync.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/galera_have_debug_sync.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB; +INSERT INTO t1 (f2) VALUES ('a'); +INSERT INTO t1 (f2) VALUES ('b'); +INSERT INTO t1 (f2) VALUES ('c'); + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a +SET SESSION wsrep_sync_wait = 0; +--let $galera_sync_point = after_certify_apply_monitor_enter +--source include/galera_set_sync_point.inc + +--connection node_2 +SET SESSION wsrep_trx_fragment_size = 64; +--send DELETE FROM t1 ORDER BY f1 DESC LIMIT 2; + +--connection node_2a +--source include/galera_wait_sync_point.inc + +--connection node_1 +INSERT INTO t1 (f2) VALUES ('d'),('e'); + +--connection node_2a +--source include/galera_signal_sync_point.inc +--source include/galera_clear_sync_point.inc + +--connection node_2 +--error ER_LOCK_DEADLOCK, ER_QUERY_INTERRUPTED +--reap + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/GCF-1018B.test b/mysql-test/suite/galera_sr/t/GCF-1018B.test new file mode 100644 index 00000000000..f11309080c0 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-1018B.test @@ -0,0 +1,40 @@ +# +# SR: Node hang with one thread waiting in InnoDB +# +--source include/galera_cluster.inc +--source include/big_test.inc + +--connection node_1 +SET SESSION wsrep_sync_wait = 0; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 64; +SET SESSION innodb_lock_wait_timeout = 1000; + +--connection node_2 +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_trx_fragment_size = 64; +SET SESSION innodb_lock_wait_timeout = 1000; + +--let $count = 500 +--disable_query_log +while ($count) +{ + --connection node_1 + --send INSERT INTO t1 (f2) VALUES ('abc'),('abc'); + + --connection node_2 + --send DELETE FROM t1 ORDER BY f1 DESC LIMIT 2; + + --connection node_1 + --error 0,ER_LOCK_DEADLOCK,ER_DUP_ENTRY,ER_LOCK_WAIT_TIMEOUT,ER_QUERY_INTERRUPTED + --reap + + --connection node_2 + --error 0,ER_LOCK_DEADLOCK,ER_DUP_ENTRY,ER_LOCK_WAIT_TIMEOUT,ER_QUERY_INTERRUPTED + --reap + + --dec $count +} +--enable_query_log + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/GCF-1043A.test b/mysql-test/suite/galera_sr/t/GCF-1043A.test new file mode 100644 index 00000000000..c76623742d7 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-1043A.test @@ -0,0 +1,13 @@ +# +# Assertion `retval == WSREP_OK || retval == WSREP_TRX_FAIL || retval == WSREP_BF_ABORT || retval == WSREP_CONN_FAIL' failed with SR +# + +--source include/galera_cluster.inc + +--let $count = 1000; +--let $wsrep_trx_fragment_size = 1; +--let $query_node_1 = DELETE FROM t1 +--let $query_node_1a = REPLACE INTO t1 VALUES (1,'y'),(2,'x') +--let $query_node_2 = REPLACE INTO t1 VALUES (1,'y'),(2,'y'),(3,'y') + +--source suite/galera/include/galera_concurrent_test.inc diff --git a/mysql-test/suite/galera_sr/t/GCF-1043B.test b/mysql-test/suite/galera_sr/t/GCF-1043B.test new file mode 100644 index 00000000000..e3b6b7439ca --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-1043B.test @@ -0,0 +1,13 @@ +# +# Assertion `retval == WSREP_OK || retval == WSREP_TRX_FAIL || retval == WSREP_BF_ABORT || retval == WSREP_CONN_FAIL' failed with SR +# + +--source include/galera_cluster.inc + +--let $count = 1000; +--let $wsrep_trx_fragment_size = 1; +--let $query_node_1 = DELETE FROM t1 +--let $query_node_1a = INSERT INTO t1 VALUES (1,'y'),(2,'x') +--let $query_node_2 = UPDATE t1 SET f2 = 'y' WHERE f1 = 1 OR f1 = 2; + +--source suite/galera/include/galera_concurrent_test.inc diff --git a/mysql-test/suite/galera_sr/t/GCF-1051.test b/mysql-test/suite/galera_sr/t/GCF-1051.test new file mode 100644 index 00000000000..511cae93784 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-1051.test @@ -0,0 +1,52 @@ +# +# Test the case where SR is rolled back to savepoint that points to the +# very beginning of the transaction. This results in regular rollback +# rather than rollback to savepoint. +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size=1; + +# +# Test 1: regular transaction +# +--connection node_1 +START TRANSACTION; +SAVEPOINT A; +INSERT INTO t1 VALUES (1); +ROLLBACK TO SAVEPOINT A; +COMMIT; + +--connection node_1 +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_2 +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +# +# Test 2: AUTOCOMMIT OFF +# +--connection node_1 +SET AUTOCOMMIT=OFF; +SAVEPOINT A; +INSERT INTO t1 VALUES (2); +ROLLBACK TO SAVEPOINT A; +COMMIT; + +--connection node_1 +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_2 +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + + +DROP TABLE t1; + diff --git a/mysql-test/suite/galera_sr/t/GCF-1060.test b/mysql-test/suite/galera_sr/t/GCF-1060.test new file mode 100644 index 00000000000..714a5ef9f90 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-1060.test @@ -0,0 +1,9 @@ +--source include/galera_cluster.inc + +--let $count = 100; +--let $wsrep_trx_fragment_size = 1; +--let $query_node_1 = TRUNCATE TABLE t1 +--let $query_node_1a = INSERT INTO t1 VALUE (1,'x'),(2,'x'),(3,'x') +--let $query_node_2 = INSERT INTO t1 VALUE (4, 'z'); + +--source suite/galera/include/galera_concurrent_test.inc diff --git a/mysql-test/suite/galera_sr/t/GCF-437.test b/mysql-test/suite/galera_sr/t/GCF-437.test new file mode 100644 index 00000000000..4101bac7446 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-437.test @@ -0,0 +1,21 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/big_test.inc + +CREATE TABLE ten (f1 INTEGER) ENGINE=MyISAM; +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(512)) ENGINE=InnoDB; + +SET SESSION wsrep_trx_fragment_size = 2 * 1024 * 1024; + +--error ER_BINLOG_ROW_LOGGING_FAILED +INSERT INTO t1 (f2) SELECT REPEAT('x', 512) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5; + +CALL mtr.add_suppression("InnoDB: The total blob data length*"); +CALL mtr.add_suppression("WSREP: Error writing into wsrep_schema.SR: 139"); +CALL mtr.add_suppression("WSREP: Failed to write to frag table: 1"); +CALL mtr.add_suppression("WSREP: Failed to append frag to persistent storage"); + +DROP TABLE t1; +DROP table ten; diff --git a/mysql-test/suite/galera_sr/t/GCF-561.test b/mysql-test/suite/galera_sr/t/GCF-561.test new file mode 100644 index 00000000000..e092e194c14 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-561.test @@ -0,0 +1,65 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test the effect of DDL on a concurrent SR transaction +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1, 1); +INSERT INTO t1 VALUES (2, 2); +INSERT INTO t1 VALUES (3, 3); +INSERT INTO t1 VALUES (4, 4); +INSERT INTO t1 VALUES (5, 5); + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1; +--source include/wait_condition.inc +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +ALTER TABLE t1 DROP COLUMN f2; + +# SR applied before the DDL is no longer visible +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_1 +# Transaction can not continue due to DDL, implicit ROLLBACK +--error ER_LOCK_DEADLOCK +INSERT INTO t1 VALUES (6, 6); + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +# DDL is now in effect +--error ER_WRONG_VALUE_COUNT_ON_ROW +INSERT INTO t1 VALUES (6, 6); + +# But it should be possible to reissue the transaction + +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +COMMIT; + +--connection node_2 +SELECT COUNT(*) = 5 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/GCF-571.test b/mysql-test/suite/galera_sr/t/GCF-571.test new file mode 100644 index 00000000000..3ad32493a35 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-571.test @@ -0,0 +1,54 @@ +# +# GCF-571 ROLLBACK TO SAVEPOINT causes all SR records to be deleted +# + +--source include/galera_cluster.inc + +SET AUTOCOMMIT=OFF; +CREATE TABLE t1 (f1 VARCHAR(10)) ENGINE=InnoDB; + +SET SESSION wsrep_trx_fragment_size = 1; +START TRANSACTION; +INSERT INTO t1 VALUES ('%abcdef%'); +INSERT INTO t1 VALUES ('%abcdef%'); +INSERT INTO t1 VALUES ('%abcdef%'); +INSERT INTO t1 VALUES ('%abcdef%'); +SAVEPOINT A; +INSERT INTO t1 VALUES ('xyzxyz'); +INSERT INTO t1 VALUES ('xyzxyz'); +INSERT INTO t1 VALUES ('xyzxyz'); +INSERT INTO t1 VALUES ('xyzxyz'); +INSERT INTO t1 VALUES ('xyzxyz'); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%abcdef%'; +SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%xyz%'; +SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%SAVEPOINT `A`%'; + +--connection node_1 +ROLLBACK TO SAVEPOINT A; + +--connection node_1a +SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%abcdef%'; +SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%xyz%'; +SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%SAVEPOINT `A`%'; +SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%ROLLBACK TO `A`%'; + +--connection node_2 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%abcdef%'; +SELECT COUNT(*) > 0 FROM wsrep_schema.SR WHERE frag LIKE '%xyz%'; +SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%SAVEPOINT `A`%'; +SELECT COUNT(*) = 1 FROM wsrep_schema.SR WHERE frag LIKE '%ROLLBACK TO `A`%'; + +--connection node_1 +ROLLBACK; + +--connection node_1a +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_2 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/GCF-572.test b/mysql-test/suite/galera_sr/t/GCF-572.test new file mode 100644 index 00000000000..8bf57a38fdd --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-572.test @@ -0,0 +1,54 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(10)) ENGINE=InnoDB; + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 + +# +# Test 1: statement rollback is not safe +# (some fragments were already replicated) +# + +--connection node_1 +SET SESSION wsrep_trx_fragment_size = 1; +START TRANSACTION; +INSERT INTO t1 VALUES (1, 'node1'); + +--connection node_1a +INSERT INTO t1 VALUES (5, 'node2'); + +--connection node_1 +# If we try to INSERT a duplicate key, ER_LOCK_DEADLOCK is the only possible +# outcome at this point. Notice that ER_DUP_ENTRY is NOT an option here +# because we were forced to rollback the whole transaction (not just the +# statement) +--error ER_LOCK_DEADLOCK +INSERT INTO t1 VALUES (5, 'node1'); + +SELECT * FROM t1; + +# +# Test 2: statement rollback is safe +# (no fragments have been replicated) +# + +SET SESSION wsrep_trx_fragment_size = 10000; + +START TRANSACTION; +INSERT INTO t1 VALUE (10, 'node1'); +SELECT * FROM wsrep_schema.SR; + +--connection node_1a +INSERT INTO t1 VALUES(15, 'node2'); + +--connection node_1 +SELECT * FROM t1; +# This time, only the statement is rolled back and we expect ER_DUP_ENTRY. +--error ER_DUP_ENTRY +INSERT INTO t1 VALUES(15, 'node1'); + +COMMIT; +SELECT * FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/GCF-574.test b/mysql-test/suite/galera_sr/t/GCF-574.test new file mode 100644 index 00000000000..c9d7c405d14 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-574.test @@ -0,0 +1,27 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test CREATE TABLE ... SELECT with Streaming Replication +# + +--connection node_1 +CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); + +--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` + +SET SESSION wsrep_trx_fragment_size = 1; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; + +--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--disable_query_log +--eval SELECT ($wsrep_last_committed_after - $wsrep_last_committed_before) > 1 AS wsrep_last_committed_delta; +--enable_query_log + +--connection node_2 +SELECT COUNT(*) = 10000 FROM t1; + +--connection node_1 +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera_sr/t/GCF-580.test b/mysql-test/suite/galera_sr/t/GCF-580.test new file mode 100644 index 00000000000..165b1abcc7a --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-580.test @@ -0,0 +1,27 @@ +# +# GCF-580 wsrep_last_committed_counter increases twice for every SR fragment +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +SET SESSION wsrep_trx_fragment_size = 1; +--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` + +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); + +--let $fragments_count = `SELECT COUNT(*) FROM wsrep_schema.SR` +--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--disable_query_log +--eval SELECT ($wsrep_last_committed_after - $wsrep_last_committed_before) = $fragments_count AS last_committed_matches_fragment_count +--enable_query_log + +COMMIT; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/GCF-585.test b/mysql-test/suite/galera_sr/t/GCF-585.test new file mode 100644 index 00000000000..af800154b0b --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-585.test @@ -0,0 +1,40 @@ +# +# GCF-585 SR: Assertion `total_length + wsrep_get_fragment_base(thd) == saved_pos' failed in wsrep_write_cache_once after SQL error +# + +--source include/galera_cluster.inc + +# Test case #1 + +create table t1 (f1 integer primary key) engine=innodb; +set autocommit=off; +set session wsrep_trx_fragment_size=1; +start transaction; +insert into t1 values (1); +--error ER_LOCK_DEADLOCK +insert into t1 values (2),(1); +alter table t1 drop primary key; +drop table t1; + +# Test case #2 + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); + +SET SESSION wsrep_trx_fragment_size=1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +update t1 set f1 = 100 where f1 = 10; + +--connection node_2 +INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20); +SET SESSION wsrep_trx_fragment_size=1; +SET SESSION innodb_lock_wait_timeout=1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +--error ER_LOCK_DEADLOCK +delete from t1 where f1 > 10; +--error ER_LOCK_DEADLOCK +delete from t1 where f1 > 10 and f1 < 100; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/GCF-597.test b/mysql-test/suite/galera_sr/t/GCF-597.test new file mode 100644 index 00000000000..d3d80ffc4f8 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-597.test @@ -0,0 +1,29 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; + +SET wsrep_trx_fragment_size = 1; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +--connection node_2 +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1); + +--connection node_1 +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connection node_2 +--error ER_LOCK_DEADLOCK +ROLLBACK; + +DROP TABLE t1;
\ No newline at end of file diff --git a/mysql-test/suite/galera_sr/t/GCF-620.test b/mysql-test/suite/galera_sr/t/GCF-620.test new file mode 100644 index 00000000000..abfba47ee5a --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-620.test @@ -0,0 +1,22 @@ +# +# GCF-620 SR: ROLLBACK TO SAVEPOINT causes slave crash if wsrep_trx_fragment_size does not fall on boundary +# + +--source include/galera_cluster.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size = 200; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (1); +SAVEPOINT A; +INSERT INTO t1 VALUES (1); +ROLLBACK TO SAVEPOINT A; +COMMIT; + +--connection node_2 +SELECT COUNT(*) = 2 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/GCF-623.test b/mysql-test/suite/galera_sr/t/GCF-623.test new file mode 100644 index 00000000000..daf9eccfa74 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-623.test @@ -0,0 +1,31 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +ALTER TABLE t1 ADD COLUMN f2 INTEGER; + +--connection node_2 +SELECT COUNT(*) = 0 FROM t1; + +--connection node_1 +--error ER_LOCK_DEADLOCK +COMMIT; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_2 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +DROP TABLE t1;
\ No newline at end of file diff --git a/mysql-test/suite/galera_sr/t/GCF-627.test b/mysql-test/suite/galera_sr/t/GCF-627.test new file mode 100644 index 00000000000..7c9faff78a8 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-627.test @@ -0,0 +1,30 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER); + +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1, 'a'); + +--connection node_2 +DROP TABLE t1; + +--connection node_1 +--error ER_LOCK_DEADLOCK +COMMIT; + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--error ER_NO_SUCH_TABLE +INSERT INTO t1 VALUES (2); + +--connection node_1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_2 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +DROP TABLE t2; diff --git a/mysql-test/suite/galera_sr/t/GCF-845.test b/mysql-test/suite/galera_sr/t/GCF-845.test new file mode 100644 index 00000000000..9651bde014d --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-845.test @@ -0,0 +1,30 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE IF NOT EXISTS t1 (f1 INTEGER) ENGINE = InnoDB; + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +SET SESSION AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size = 1; +INSERT INTO t1 VALUES (161); +COMMIT; +DELETE FROM t1 WHERE f1 > 13; +--disconnect node_1a +--sleep 2 + +--connection node_2 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +DROP TABLE t1; + +--let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.2.err +--let $assert_count = 0 +--let $assert_select = BF-BF X +--let $assert_text = No BF-BF log line found +--let $assert_only_after = CURRENT_TEST +--source include/assert_grep.inc + diff --git a/mysql-test/suite/galera_sr/t/GCF-851.test b/mysql-test/suite/galera_sr/t/GCF-851.test new file mode 100644 index 00000000000..a9b7725c155 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-851.test @@ -0,0 +1,24 @@ +--source include/galera_cluster.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +SET SESSION WSREP_TRX_FRAGMENT_SIZE=1; +SET SESSION AUTOCOMMIT=OFF; + +INSERT INTO t1 VALUES (10); +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +--connection node_2 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +--connection node_1 +START TRANSACTION; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_2 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +SELECT COUNT(*) > 0 FROM t1; + +--connection node_1 +SELECT COUNT(*) > 0 FROM t1; +DROP TABLE t1; + diff --git a/mysql-test/suite/galera_sr/t/GCF-867.test b/mysql-test/suite/galera_sr/t/GCF-867.test new file mode 100644 index 00000000000..73ae43237c9 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-867.test @@ -0,0 +1,42 @@ +# +# Test many ongoing SR transactions +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; +--disable_query_log + +--let $connections = 120 + +--let $count = $connections +while ($count) +{ +--connect $count, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET SESSION wsrep_trx_fragment_size = 1; +SET SESSION wsrep_sync_wait = 0; +--dec $count +} + + +--let $count = $connections +while ($count) +{ +--connection $count +START TRANSACTION; +--send_eval INSERT INTO t1 VALUES ($count) +--dec $count +} + +--let $count = $connections +while ($count) +{ +--connection $count +--reap +COMMIT; +--dec $count +} + +--enable_query_log +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/GCF-889.test b/mysql-test/suite/galera_sr/t/GCF-889.test new file mode 100644 index 00000000000..fa2a417d8ce --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-889.test @@ -0,0 +1,28 @@ +--source include/galera_cluster.inc + +--connection node_2 +SET GLOBAL wsrep_ignore_apply_errors = 2; + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +SET SESSION wsrep_on = OFF; +INSERT INTO t1 VALUES (1); +SET SESSION wsrep_on = ON; + +SET SESSION wsrep_trx_fragment_size = 1; +DELETE FROM t1 WHERE f1 = 1; +SET SESSION wsrep_trx_fragment_size = 0; + +INSERT INTO t1 VALUES (1); + +SELECT COUNT(*) = 1; + +--connection node_2 +SELECT COUNT(*) = 1; +CALL mtr.add_suppression("Could not execute Delete_rows event on table"); +SET GLOBAL wsrep_ignore_apply_errors = 7; + +--connection node_1 +DROP TABLE t1; + diff --git a/mysql-test/suite/galera_sr/t/GCF-900.test b/mysql-test/suite/galera_sr/t/GCF-900.test new file mode 100644 index 00000000000..3f1b53630b6 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-900.test @@ -0,0 +1,28 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INT PRIMARY KEY, f2 INT) ENGINE=InnoDB; + +--connection node_1 +SET SESSION wsrep_trx_fragment_size = 128; +START TRANSACTION; +INSERT INTO t1 VALUES (1, 0); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +SET SESSION wsrep_trx_fragment_size = 1; +START TRANSACTION; +INSERT INTO t1 VALUES (2, 0); + +--connection node_2 +ALTER TABLE t1 DROP COLUMN f2; + +--connection node_1 +--error ER_LOCK_DEADLOCK +COMMIT; + +--connection node_1a +--error ER_LOCK_DEADLOCK +INSERT INTO t1 VALUES (3, 0); + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/disabled.def b/mysql-test/suite/galera_sr/t/disabled.def new file mode 100644 index 00000000000..e5511d18860 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/disabled.def @@ -0,0 +1,4 @@ +mysql-wsrep-features#29 : binlog_format=STATEMENT not supported with SR +GCF-574 : CTAS is not supported together with SR +galera_sr_bf_abort : is worked on with tracker GCF-1015 +galera_sr_sbr : binlog_format=STATEMENT not supported with SR diff --git a/mysql-test/suite/galera_sr/t/galera-features#56.test b/mysql-test/suite/galera_sr/t/galera-features#56.test new file mode 100644 index 00000000000..0497952e355 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera-features#56.test @@ -0,0 +1,55 @@ +## +## This test tests parallel application of multiple auto-increment insert transactions +## + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# Create a second connection to node1 so that we can run transactions concurrently +--let $galera_connection_name = node_1a +--let $galera_server_number = 1 +--source include/galera_connect.inc +SET SESSION wsrep_trx_fragment_size = 1; + +--connection node_1 +CREATE TABLE ten (f1 INTEGER); +INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); + +CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 INTEGER) Engine=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; + + +--connection node_2 +--let $wsrep_slave_threads_orig = `SELECT @@wsrep_slave_threads` +SET GLOBAL wsrep_slave_threads = 4; +SET SESSION wsrep_trx_fragment_size = 1; + +--connection node_1 +--send INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; + +--connection node_1a +--send INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; + +--connection node_2 +--send INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; + +--connection node_1 +--reap + +--connection node_1a +--reap + +--connection node_2 +--reap + +SELECT COUNT(*) = 30000 FROM t1; +SELECT COUNT(DISTINCT f1) = 30000 FROM t1; +SELECT COUNT(*) = 6 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'; + +--disable_query_log +--eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig; +--enable_query_log + +--connection default +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_bf_abort.inc b/mysql-test/suite/galera_sr/t/galera_sr_bf_abort.inc new file mode 100644 index 00000000000..eba84eddb93 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_bf_abort.inc @@ -0,0 +1,145 @@ +# +# Test SR BF abort for all sync points in master side code path +# +# The procedure in all test cases is the following: +# 1) Start SR transaction on node 1, do INSERT + SELECT .. FOR UPDATE +# 2) Set up sync point on node 1 to block slave thread processing +# in apply monitor +# 3) Do write on node 2 which will conflict with SELECT .. FOR UPDATE +# 4) Set up desired sync point on master side and commit +# 5) Wait until commit reaches master side sync point, clear sync points +# and release all sync point waiters +# 6) COMMIT on node 1 should return deadlock error +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +--eval SET SESSION wsrep_trx_fragment_size = $wsrep_trx_fragment_size +SET AUTOCOMMIT=OFF; + +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 FOR UPDATE; + +# Set up sync point +--connection node_1a +--let galera_sync_point = apply_monitor_slave_enter_sync +--source include/galera_set_sync_point.inc + +# Conflicting insert +--connection node_2 + +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (2); + +--connection node_1a +--source include/galera_wait_sync_point.inc +--source include/galera_clear_sync_point.inc +--let $galera_sync_point = $galera_sr_bf_abort_sync_point +--source include/galera_set_sync_point.inc + +--connection node_1 +if ($galera_sr_bf_abort_at_commit) +{ + --send COMMIT +} +if (!$galera_sr_bf_abort_at_commit) +{ + --send INSERT INTO t1 VALUES (3) +} + +--connection node_1a + +--let $cmp = `SELECT STRCMP('apply_monitor_slave_enter_sync', '$galera_sr_bf_abort_sync_point') = -1` + +if ($cmp) +{ + --let $galera_sync_point = apply_monitor_slave_enter_sync $galera_sr_bf_abort_sync_point +} +if (!$cmp) +{ + --let $galera_sync_point = $galera_sr_bf_abort_sync_point apply_monitor_slave_enter_sync +} +--source include/galera_wait_sync_point.inc + +# Let conflicting insert proceed, make sure it hits abort_trx_end and +# let both threads continue. + +--source include/galera_clear_sync_point.inc +--let $galera_sync_point = abort_trx_end +--source include/galera_set_sync_point.inc +--let $galera_sync_point = apply_monitor_slave_enter_sync +--source include/galera_signal_sync_point.inc +--let $galera_sync_point = abort_trx_end $galera_sr_bf_abort_sync_point + +--source include/galera_wait_sync_point.inc +--source include/galera_clear_sync_point.inc +--let $galera_sync_point = abort_trx_end +--source include/galera_signal_sync_point.inc +--let $galera_sync_point = $galera_sr_bf_abort_sync_point +--source include/galera_signal_sync_point.inc + +# Deadlock should now be retured by node_1 +--connection node_1 +if (!$galera_sr_bf_abort_at_commit) +{ + --error ER_LOCK_DEADLOCK + --reap +} +if ($galera_sr_bf_abort_at_commit) +{ + --reap +} + +ROLLBACK; + +# Release slave insert +--connection node_1a +--source include/galera_clear_sync_point.inc +--let $galera_sync_point = abort_trx_end +--source include/galera_signal_sync_point.inc + +# Verify that nodes are consistent + +# End result: +# If the statement which was BF aborted was commit, +# node_1 must replay the transaction so that the table +# will have rows 1, 2. If it in turn was INSERT, +# node_1 must abort the transaction so that only +# INSERT ... VALUES (2) survives. + +--connection node_1 +SELECT * FROM t1; +if ($galera_sr_bf_abort_at_commit) +{ + SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; + SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +} +if (!$galera_sr_bf_abort_at_commit) +{ + SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +} +--connection node_2 +SELECT * FROM t1; +if ($galera_sr_bf_abort_at_commit) +{ + SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 1; + SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +} +if (!$galera_sr_bf_abort_at_commit) +{ + SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +} + +--connection node_1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +--connection node_2 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +# Delete entery to verify that node is unblocked +--connection node_1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_bf_abort.test b/mysql-test/suite/galera_sr/t/galera_sr_bf_abort.test new file mode 100644 index 00000000000..711ef69bd14 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_bf_abort.test @@ -0,0 +1,48 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--let $wsrep_trx_fragment_size = 1 + +# Control connection for manipulating sync points on node 1 +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET SESSION wsrep_sync_wait = 0; + +--echo galera_sr_bf_abort_at_commit = 0 +--let $galera_sr_bf_abort_at_commit = 0 + +--echo after_replicate_sync +--let $galera_sr_bf_abort_sync_point = after_replicate_sync +--source galera_sr_bf_abort.inc + +--echo local_monitor_master_enter_sync +--let $galera_sr_bf_abort_sync_point = local_monitor_master_enter_sync +--source galera_sr_bf_abort.inc + +--echo apply_monitor_master_enter_sync +--let $galera_sr_bf_abort_sync_point = apply_monitor_master_enter_sync +--source galera_sr_bf_abort.inc + +--echo commit_monitor_master_enter_sync +--let $galera_sr_bf_abort_sync_point = commit_monitor_master_enter_sync +--source galera_sr_bf_abort.inc + +--echo galera_sr_bf_abort_at_commit = 1 +--let $galera_sr_bf_abort_at_commit = 1 + +--echo after_replicate_sync +--let $galera_sr_bf_abort_sync_point = after_replicate_sync +--source galera_sr_bf_abort.inc + +--echo local_monitor_master_enter_sync +--let $galera_sr_bf_abort_sync_point = local_monitor_master_enter_sync +--source galera_sr_bf_abort.inc + +--echo apply_monitor_master_enter_sync +--let $galera_sr_bf_abort_sync_point = apply_monitor_master_enter_sync +--source galera_sr_bf_abort.inc + +--echo commit_monitor_master_enter_sync +--let $galera_sr_bf_abort_sync_point = commit_monitor_master_enter_sync +--source galera_sr_bf_abort.inc + +CALL mtr.add_suppression("WSREP: fragment replication failed: 1"); diff --git a/mysql-test/suite/galera_sr/t/galera_sr_blob.test b/mysql-test/suite/galera_sr/t/galera_sr_blob.test new file mode 100644 index 00000000000..ed314d09f5a --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_blob.test @@ -0,0 +1,38 @@ +# +# Test that a single-blob will be replicated using SR if it is sufficiently +# large. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +CREATE TABLE t1 (f1 TEXT) ENGINE=InnoDB; + +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +--connection node_2 +--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` + +--connection node_1 +INSERT INTO t1 VALUES (REPEAT('x', 65535)); + +--connection node_2 +--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` + +# Confirm that exactly one fragment was replicated + +--disable_query_log +--eval SELECT ($wsrep_last_committed_after - $wsrep_last_committed_before) = 1 AS wsrep_last_committed_delta; +--enable_query_log + +--connection node_1 +COMMIT; + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; +SELECT LENGTH(f1) = 65535 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_cc_master.test b/mysql-test/suite/galera_sr/t/galera_sr_cc_master.test new file mode 100644 index 00000000000..7a4e1706402 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_cc_master.test @@ -0,0 +1,87 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test the effect of Cluster Configuration Change on a concurrently-running SR transaction +# We use SET GLOBAL wsrep_cluster_address = '' to cause the master (node_2) to temporarily +# leave the cluster. +# + +--connection node_2 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size` +SET SESSION wsrep_trx_fragment_size = 1; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +--connection node_1 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +# +# Trigger CC . The transaction is aborted and we expect the SR tables to be cleaned up +# + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a +--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address` +SET GLOBAL wsrep_cluster_address = ''; + +--sleep 2 +--connection node_2 + +--error 2013,ER_UNKNOWN_COM_ERROR +INSERT INTO t1 VALUES (6); + +--connection node_1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +# Restore cluster + +--connection node_2a +--disable_query_log +--eval SET GLOBAL wsrep_cluster_address='gcomm://127.0.0.1:$NODE_GALERAPORT_1'; +--enable_query_log +--sleep 2 + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + + +--connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2b +--source include/galera_wait_ready.inc +SELECT * FROM wsrep_schema.SR; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +# Repeat transaction to confirm no locks are left from previous transaction + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +COMMIT; + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_1 +SELECT COUNT(*) = 5 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +DROP TABLE t1; + +--connection node_2b +CALL mtr.add_suppression("WSREP: failed to send SR rollback for"); + diff --git a/mysql-test/suite/galera_sr/t/galera_sr_cc_slave.test b/mysql-test/suite/galera_sr/t/galera_sr_cc_slave.test new file mode 100644 index 00000000000..148539bf5b0 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_cc_slave.test @@ -0,0 +1,86 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test the effect of Cluster Configuration Change on a concurrently-running SR transaction +# We use SET GLOBAL wsrep_cluster_address = '' to cause the slave (node_2) to temporarily +# leave the cluster. +# + +# Start with a clean slate +--connection node_2 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size` +SET SESSION wsrep_trx_fragment_size = 1; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +--connection node_2 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +# +# Trigger CC . The transaction should be able to continue +# + +--connection node_2 +--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address` +SET GLOBAL wsrep_cluster_address = ''; +--sleep 2 + +--connection node_1 +# Continue generating events in the transaction + +INSERT INTO t1 VALUES (6); +INSERT INTO t1 VALUES (7); +INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (9); +INSERT INTO t1 VALUES (10); + +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +# Restore cluster + +--connection node_2 +--disable_query_log +--eval SET GLOBAL wsrep_cluster_address='gcomm://127.0.0.1:$NODE_GALERAPORT_1'; +--enable_query_log +--sleep 2 +--source include/galera_wait_ready.inc + +# Confirm that the SR table still contains entries from ongoing transaction +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +# Continue and finalize transaction +--connection node_1 +INSERT INTO t1 VALUES (11); +INSERT INTO t1 VALUES (12); +INSERT INTO t1 VALUES (13); +INSERT INTO t1 VALUES (14); +INSERT INTO t1 VALUES (16); +COMMIT; + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +# Confirm that transaction was replicated properly +# and SR table is cleaned up afterwards. + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 15 FROM t1; +--source include/wait_condition.inc + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_concurrent.test b/mysql-test/suite/galera_sr/t/galera_sr_concurrent.test new file mode 100644 index 00000000000..9ec7143d25c --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_concurrent.test @@ -0,0 +1,45 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test two concurrent SR-replicated transactions +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size` +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t2 VALUES (1); +INSERT INTO t2 VALUES (2); +INSERT INTO t2 VALUES (3); +INSERT INTO t2 VALUES (4); +INSERT INTO t2 VALUES (5); + +--connection node_1 +COMMIT; + +--connection node_1a +COMMIT; + +--connection node_2 +SELECT COUNT(*) = 5 FROM t1; +SELECT COUNT(*) = 5 FROM t2; + +--connection node_1 + +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_conflict.test b/mysql-test/suite/galera_sr/t/galera_sr_conflict.test new file mode 100644 index 00000000000..dd033fec9c7 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_conflict.test @@ -0,0 +1,45 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# A conflict between a streaming replication fragment and a local transaction +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connection node_2 +# Wait until a streaming replication fragment has arrived +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1; +--source include/wait_condition.inc + +# Attempt a conflicting INSERT. This will block +--send INSERT INTO t1 VALUES(1); + +# Observe the block from a separate connection +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 + +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'committed%'; +--source include/wait_condition.inc + +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'update'; +--source include/wait_condition.inc + +# Commit the remote transaction, causing the local transaction to return an error +--connection node_1 +COMMIT; + +--connection node_2 +--error ER_DUP_ENTRY +--reap + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_conflict_on_commit.test b/mysql-test/suite/galera_sr/t/galera_sr_conflict_on_commit.test new file mode 100644 index 00000000000..6675321641f --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_conflict_on_commit.test @@ -0,0 +1,45 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test the following sequence of events: +# +# 1. Node #2 begins a transaction +# 2. Node #1 begins conflicting transaction that is SR replicated +# 3. Node #2 attempts to commit, gets a deadlock error, even before #1 has committed +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +--connection node_2 +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1); + +--connection node_1 +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connection node_2 +--error ER_LOCK_DEADLOCK +COMMIT; + +--connection node_1 +COMMIT; + +SELECT COUNT(*) = 5 FROM t1; + +--connection node_2 +SELECT COUNT(*) = 5 FROM t1; + +--connection node_1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_conflict_on_commit2.test b/mysql-test/suite/galera_sr/t/galera_sr_conflict_on_commit2.test new file mode 100644 index 00000000000..0ea52290bb6 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_conflict_on_commit2.test @@ -0,0 +1,46 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test the following sequence of events: +# +# 1. Node #1 begins a transaction that is SR replicated +# 2. Node #2 begins a conflicting transaction, hangs +# 3. Node #1 comits +# 4. Node #2 gets a dup key error +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; + +SET SESSION wsrep_trx_fragment_size = 1; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +--connection node_1 +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connection node_2 +--send INSERT INTO t1 VALUES (5); + +--sleep 1 + +--connection node_1 +COMMIT; + +--connection node_2 +--error ER_DUP_ENTRY +--reap + +SELECT COUNT(*) = 5 FROM t1; + +--connection node_2 +SELECT COUNT(*) = 5 FROM t1; + +--connection node_1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_conflict_with_rollback_master.test b/mysql-test/suite/galera_sr/t/galera_sr_conflict_with_rollback_master.test new file mode 100644 index 00000000000..cb96fae0122 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_conflict_with_rollback_master.test @@ -0,0 +1,44 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test the following sequence of events: +# +# 1. Node #2 begins a transaction +# 2. Node #1 begins conflicting transaction that is SR replicated +# 3. Node #1 rolls back +# 4. Node #2 can not commit because it was BF-aborted even though the SR transaction was rolled back +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; + +SET SESSION wsrep_trx_fragment_size = 1; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +--connection node_2 +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1); + +--connection node_1 +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +ROLLBACK; + +--connection node_2 +--error ER_LOCK_DEADLOCK +COMMIT; + +SELECT COUNT(*) = 0 FROM t1; + +--connection node_1 +SELECT COUNT(*) = 0 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_ddl_master.test b/mysql-test/suite/galera_sr/t/galera_sr_ddl_master.test new file mode 100644 index 00000000000..105d395df6b --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_ddl_master.test @@ -0,0 +1,63 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test the following sequence of events on the master: +# +# 1. Connection #1 begins a SR transaction +# 2. Connection #2 issues DDL +# 3. Connection #1 attempts to continue the transaction, gets deadlock +# 4. Connection #1 retries the transaction and succeeds +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +SET SESSION wsrep_trx_fragment_size = 1; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connection node_2 +# SR replication is triggered and rows have been delivered to the slave +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1; +--source include/wait_condition.inc + +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +ALTER TABLE t1 ADD COLUMN f2 INTEGER; + +--connection node_1 +--error ER_LOCK_DEADLOCK +INSERT INTO t1 VALUES (6); + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +# Check that the transaction thus aborted could be reissued + +ROLLBACK; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES (1); +INSERT INTO t1 (f1) VALUES (2); +INSERT INTO t1 (f1) VALUES (3); +INSERT INTO t1 (f1) VALUES (4); +INSERT INTO t1 (f1) VALUES (5); +INSERT INTO t1 (f1) VALUES (6); +COMMIT; + +SELECT COUNT(*) = 6 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_2 +SELECT COUNT(*) = 6 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_ddl_schema.test b/mysql-test/suite/galera_sr/t/galera_sr_ddl_schema.test new file mode 100644 index 00000000000..a3045773387 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_ddl_schema.test @@ -0,0 +1,43 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test the effect of DROP SCHEMA DDL on a concurrent SR transaction +# Most other DDL tests work on a table level, so this test exercises a +# different granularity. +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1, 1); +INSERT INTO t1 VALUES (2, 2); +INSERT INTO t1 VALUES (3, 3); +INSERT INTO t1 VALUES (4, 4); +INSERT INTO t1 VALUES (5, 5); + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1; +--source include/wait_condition.inc + +DROP SCHEMA test; + +--error ER_NO_SUCH_TABLE +SELECT COUNT(*) = 0 FROM test.t1; + +--connection node_1 + +# Transaction can not continue due to DDL +--error ER_LOCK_DEADLOCK +INSERT INTO test.t1 VALUES (6, 6); + +# DDL is now in effect +--error ER_NO_SUCH_TABLE +INSERT INTO test.t1 VALUES (6, 6); + +CREATE SCHEMA test; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_ddl_slave.test b/mysql-test/suite/galera_sr/t/galera_sr_ddl_slave.test new file mode 100644 index 00000000000..e092e194c14 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_ddl_slave.test @@ -0,0 +1,65 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test the effect of DDL on a concurrent SR transaction +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1, 1); +INSERT INTO t1 VALUES (2, 2); +INSERT INTO t1 VALUES (3, 3); +INSERT INTO t1 VALUES (4, 4); +INSERT INTO t1 VALUES (5, 5); + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1; +--source include/wait_condition.inc +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +ALTER TABLE t1 DROP COLUMN f2; + +# SR applied before the DDL is no longer visible +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_1 +# Transaction can not continue due to DDL, implicit ROLLBACK +--error ER_LOCK_DEADLOCK +INSERT INTO t1 VALUES (6, 6); + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +# DDL is now in effect +--error ER_WRONG_VALUE_COUNT_ON_ROW +INSERT INTO t1 VALUES (6, 6); + +# But it should be possible to reissue the transaction + +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +COMMIT; + +--connection node_2 +SELECT COUNT(*) = 5 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_ddl_unrelated.test b/mysql-test/suite/galera_sr/t/galera_sr_ddl_unrelated.test new file mode 100644 index 00000000000..49155017d3f --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_ddl_unrelated.test @@ -0,0 +1,53 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test the effect of unrelated DDL on a concurrent SR transaction +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1, 1); +INSERT INTO t1 VALUES (2, 2); +INSERT INTO t1 VALUES (3, 3); +INSERT INTO t1 VALUES (4, 4); +INSERT INTO t1 VALUES (5, 5); + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1; +--source include/wait_condition.inc +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +ALTER TABLE t2 DROP COLUMN f2; + +# SR applied before the DDL is still visible +SELECT COUNT(*) = 5 FROM t1; +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +--connection node_1 + +# Transaction can continue, even after the DDL +--error 0 +INSERT INTO t1 VALUES (6, 6); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +COMMIT; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_2 +SELECT COUNT(*) = 6 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_dupkey_error.test b/mysql-test/suite/galera_sr/t/galera_sr_dupkey_error.test new file mode 100644 index 00000000000..c9d7770736b --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_dupkey_error.test @@ -0,0 +1,57 @@ +# +# Test the case where a duplicate key error happens in the middle of an SR transaction +# + +--source include/galera_cluster.inc + +CREATE TABLE t1 (f1 BLOB) ENGINE=InnoDB; +CREATE UNIQUE INDEX i1 ON t1 (f1(512)); + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +SET SESSION wsrep_trx_fragment_size = 1024; + +INSERT INTO t1 VALUES (REPEAT('a', 512)); +INSERT INTO t1 VALUES (REPEAT('b', 512)); +INSERT INTO t1 VALUES (REPEAT('c', 512)); +INSERT INTO t1 VALUES (REPEAT('d', 512)); +INSERT INTO t1 VALUES (REPEAT('e', 512)); +INSERT INTO t1 VALUES (REPEAT('f', 512)); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +--connection node_1 +--error ER_LOCK_DEADLOCK +INSERT INTO t1 VALUES (REPEAT('c', 512)); + +# Confirm that the wsrep_schema table is now empty, as it was a full transaction rollback + +--connection node_1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +--connection node_2 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +# Confirm that the transaction can be restarted on either node + +--connection node_1 +INSERT INTO t1 VALUES (REPEAT('d', 512)); +INSERT INTO t1 VALUES (REPEAT('e', 512)); +INSERT INTO t1 VALUES (REPEAT('f', 512)); +COMMIT; + +--connection node_2 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (REPEAT('a', 512)); +INSERT INTO t1 VALUES (REPEAT('b', 512)); +INSERT INTO t1 VALUES (REPEAT('c', 512)); +COMMIT; + +--connection node_1 +SELECT COUNT(*) = 6 FROM t1; + +--connection node_2 +SELECT COUNT(*) = 6 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_fk_conflict.test b/mysql-test/suite/galera_sr/t/galera_sr_fk_conflict.test new file mode 100644 index 00000000000..b83deaee244 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_fk_conflict.test @@ -0,0 +1,62 @@ +# +# Test Foreign Key with SR +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE grandparent ( + id INT NOT NULL PRIMARY KEY +) ENGINE=InnoDB; + +CREATE TABLE parent ( + id INT NOT NULL PRIMARY KEY, + grandparent_id INT, + FOREIGN KEY (grandparent_id) + REFERENCES grandparent(id) + ON UPDATE CASCADE +) ENGINE=InnoDB; + +CREATE TABLE child ( + id INT NOT NULL PRIMARY KEY, + grandparent_id INT, + FOREIGN KEY (grandparent_id) + REFERENCES parent(grandparent_id) + ON UPDATE CASCADE +) ENGINE=InnoDB; + +INSERT INTO grandparent VALUES (1),(2),(3),(4); +INSERT INTO parent VALUES (1,1), (2,2); +INSERT INTO child VALUES (1,1), (2,2); + +# Start and SR transaction + +--connection node_1 +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size = 1; +START TRANSACTION; + +UPDATE grandparent SET id = 5 WHERE id = 1; + +# No conflicting transactions are allowed to proceed on slave + +--connection node_2 +SET SESSION innodb_lock_wait_timeout = 1; + +--error ER_LOCK_WAIT_TIMEOUT +UPDATE grandparent SET id = 10 WHERE id = 5; + +--error ER_LOCK_WAIT_TIMEOUT +DELETE FROM child; + +# SR transaction succesffull + +--connection node_1 +COMMIT; + +--let $diff_servers = 1 2 +--source include/diff_servers.inc + +DROP TABLE child; +DROP TABLE parent; +DROP TABLE grandparent; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_gtid-master.opt b/mysql-test/suite/galera_sr/t/galera_sr_gtid-master.opt new file mode 100644 index 00000000000..d5176463cdb --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_gtid-master.opt @@ -0,0 +1 @@ +--gtid-mode=ON --log-bin --log-slave-updates --enforce-gtid-consistency --loose-galera-sr-gtid-unique diff --git a/mysql-test/suite/galera_sr/t/galera_sr_gtid.test b/mysql-test/suite/galera_sr/t/galera_sr_gtid.test new file mode 100644 index 00000000000..fbb61588452 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_gtid.test @@ -0,0 +1,46 @@ +# +# Test basic Galera operation under --gtid-mode=ON +# + +--source include/have_log_bin.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INT PRIMARY KEY); + +SET SESSION wsrep_trx_fragment_size=1; +INSERT INTO t1 VALUES (1); + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; + +SET SESSION wsrep_trx_fragment_size=1; +UPDATE t1 SET f1 = 2; + +--let $gtid_executed_node2 = `SELECT @@global.gtid_executed;` + +--connection node_1 +SET SESSION wsrep_trx_fragment_size=0; + +--connection node_2 +SET SESSION wsrep_trx_fragment_size=0; + +--connection node_1 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; + +--disable_query_log +--eval SELECT '$gtid_executed_node2' = @@global.gtid_executed AS gtid_executed_equal; +--enable_query_log + +--replace_regex /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/<GTID>/ /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/ +--replace_column 2 <Pos> 5 <End_log_pos> +SHOW BINLOG EVENTS IN 'mysqld-bin.000002' FROM 120; + +--connection node_2 +# Perform causal wait +SELECT 1 FROM DUAL; +--replace_regex /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/<GTID>/ /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/ +--replace_column 2 <Pos> 5 <End_log_pos> +SHOW BINLOG EVENTS IN 'mysqld-bin.000003' FROM 120; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_insert_select.test b/mysql-test/suite/galera_sr/t/galera_sr_insert_select.test new file mode 100644 index 00000000000..01481db5a8b --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_insert_select.test @@ -0,0 +1,33 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test large INSERT ... SELECT with SR +# + +--connection node_1 +CREATE TABLE ten (f1 INTEGER); +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +# Insert 10K rows. +INSERT INTO t1 (f2) SELECT REPEAT('a', 255) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 99 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +COMMIT; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 10000 FROM t1; + +--connection node_1 + +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_all_nobootstrap.test b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_nobootstrap.test new file mode 100644 index 00000000000..2730af7f9f4 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_nobootstrap.test @@ -0,0 +1,52 @@ +# +# Kill entire cluster during SR while pc.bootstrap is in effect +# after restart, confirm that the wsrep_schema.SR table is empty +# + +--source include/galera_cluster.inc +--source include/big_test.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +--source include/wait_condition.inc + +--source include/kill_galera.inc +--connection node_1 +--source include/kill_galera.inc + +--sleep 1 + +# Bootstrap the cluster from scratch + +--connection node_1 +--remove_file $MYSQLTEST_VARDIR/mysqld.1/data/grastate.dat +--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--source include/start_mysqld.inc + +--connection node_2 +--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +--source include/start_mysqld.inc + +--connection node_1 +--source include/wait_until_connected_again.inc +--source include/galera_wait_ready.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_2 +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_all_norecovery.cnf b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_norecovery.cnf new file mode 100644 index 00000000000..6422d7541ba --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_norecovery.cnf @@ -0,0 +1,4 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.recovery=false' diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_all_norecovery.test b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_norecovery.test new file mode 100644 index 00000000000..dc99521f40e --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_norecovery.test @@ -0,0 +1,53 @@ +# +# Kill entire cluster during SR while pc.recovery is NOT in effect +# after restart, confirm that the wsrep_schema.SR table is empty +# + +--source include/galera_cluster.inc +--source include/big_test.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +--source include/wait_condition.inc + +--source include/kill_galera.inc +--connection node_1 +--source include/kill_galera.inc + +--sleep 1 + +--connection node_1 +--remove_file $MYSQLTEST_VARDIR/mysqld.1/data/grastate.dat +--let $start_mysqld_params = "--wsrep-new-cluster" +--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--source include/start_mysqld.inc + +--connection node_2 +--let $start_mysqld_params = "" +--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +--source include/start_mysqld.inc + +--connection node_1 +--source include/wait_until_connected_again.inc +--source include/galera_wait_ready.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_all_pcrecovery.test b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_pcrecovery.test new file mode 100644 index 00000000000..e6b1a9c5d27 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_all_pcrecovery.test @@ -0,0 +1,54 @@ +# +# Kill entire cluster during SR while pc.recovery is in effect +# after restart, confirm that the wsrep_schema.SR table is empty +# + +--source include/galera_cluster.inc +--source include/big_test.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +--source include/wait_condition.inc + +--source include/kill_galera.inc +--connection node_1 +--source include/kill_galera.inc + +--sleep 1 + +# Bootstrap the cluster from scratch + +--connection node_1 +--remove_file $MYSQLTEST_VARDIR/mysqld.1/data/grastate.dat +--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--source include/start_mysqld.inc + +--connection node_2 +--remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat +--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +--source include/start_mysqld.inc + +--connection node_1 +--source include/wait_until_connected_again.inc +--source include/galera_wait_ready.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_connection.test b/mysql-test/suite/galera_sr/t/galera_sr_kill_connection.test new file mode 100644 index 00000000000..03d09f33fab --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_connection.test @@ -0,0 +1,59 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test KILL CONNECTION on a transaction that has already replicated some data via SR +# + +SET SESSION wsrep_trx_fragment_size = 1; + +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +# Confirm that the transaction is SR-replicated +--connection node_2 +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1; +--source include/wait_condition.inc + +# Kill the transaction by killing the entire connection + +--connection node_1 +--let $connection_id = `SELECT CONNECTION_ID()` +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--disable_query_log +--eval KILL CONNECTION $connection_id +--enable_query_log + +# Confirm that the disconnection caused the updates made so far to be removed +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 0 FROM t1; +--source include/wait_condition.inc + +# Confirm that the transaction can be reissued in its entirety on the slave without a conflict + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +COMMIT; + +SELECT COUNT(*) = 5 FROM t1; + +--connection node_1a +SELECT COUNT(*) = 5 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_query.test b/mysql-test/suite/galera_sr/t/galera_sr_kill_query.test new file mode 100644 index 00000000000..c7f10ed570d --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_query.test @@ -0,0 +1,53 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/big_test.inc + +# +# Test KILL QUERY on a statement that has already replicated some data via SR +# + +SET SESSION wsrep_trx_fragment_size = 1; + +CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); + +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +--let $connection_id = `SELECT CONNECTION_ID()` +--send INSERT INTO t1 SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6; + +# Wait for some SR to arrive on the slave. +--connection node_2 +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT TABLE_ROWS > 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +--connection node_1 +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--echo Killing query ... +--disable_query_log +--eval KILL QUERY $connection_id +--enable_query_log + +--connection node_1 +--error ER_QUERY_INTERRUPTED +--reap + +# Confirm that the kill caused the updates made so far to be removed +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 0 FROM t1; +--source include/wait_condition.inc + +--let $wait_condition = SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +--source include/wait_condition.inc + +# Confirm that the transaction can be reissued in its entirety on the slave without a conflict + +INSERT INTO t1 SELECT 1 FROM ten AS t1, ten AS t2, ten AS t3; +SELECT COUNT(*) = 1000 FROM t1; + +--connection node_1a +SELECT COUNT(*) = 1000 FROM t1; + +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_slave.cnf b/mysql-test/suite/galera_sr/t/galera_sr_kill_slave.cnf new file mode 100644 index 00000000000..290d8fe196e --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_slave.cnf @@ -0,0 +1,4 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.weight=2' diff --git a/mysql-test/suite/galera_sr/t/galera_sr_kill_slave.test b/mysql-test/suite/galera_sr/t/galera_sr_kill_slave.test new file mode 100644 index 00000000000..9abce126d44 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_slave.test @@ -0,0 +1,80 @@ +# +# This test kills the slave while a Streaming Replication transaction is in +# progress but before a fragment has already been applied on the slave. It +# is expected that after the slave restarts, the cluster will continue to +# be consistent. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +# Block node #2's applier before table t1's inserts have come into play + +--connection node_2 +SELECT COUNT(*) = 0 FROM t1; + +--connection node_1 +CREATE TABLE t2 (f1 INTEGER); + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +LOCK TABLE t2 WRITE; + +--connection node_1 +INSERT INTO t2 VALUES (1); + +--connection node_2 +SET SESSION wsrep_sync_wait = 0; + +--connection node_1 +--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size` +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--sleep 2 + +--connection node_2 +--source include/kill_galera.inc +--sleep 1 + +--connection node_1 +INSERT INTO t1 VALUES (6); +INSERT INTO t1 VALUES (7); +INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (9); +INSERT INTO t1 VALUES (10); + +--connection node_2 +--source include/start_mysqld.inc +--sleep 1 + +--source include/wait_until_connected_again.inc +--source include/galera_wait_ready.inc + +--connection node_1 +INSERT INTO t1 VALUES (11); +INSERT INTO t1 VALUES (12); +INSERT INTO t1 VALUES (13); +INSERT INTO t1 VALUES (14); +INSERT INTO t1 VALUES (15); +COMMIT; + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_2 +--sleep 5 +SELECT COUNT(*) = 15 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_1 + +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_large_fragment-master.opt b/mysql-test/suite/galera_sr/t/galera_sr_large_fragment-master.opt new file mode 100644 index 00000000000..132c6aed246 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_large_fragment-master.opt @@ -0,0 +1 @@ +--innodb_log_file_size=1G --binlog-row-event-max-size=100M diff --git a/mysql-test/suite/galera_sr/t/galera_sr_large_fragment.test b/mysql-test/suite/galera_sr/t/galera_sr_large_fragment.test new file mode 100644 index 00000000000..ca54f9e6851 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_large_fragment.test @@ -0,0 +1,58 @@ +# +# Test the replication and subsequent cleanup of a few, very large fragments +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/big_test.inc + +CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(512)) ENGINE=InnoDB; + +SET SESSION wsrep_trx_fragment_size = 1024 * 1024 * 10; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 (f2) SELECT REPEAT('x', 512) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5; + +--connection node_2 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) > 50000 FROM t1; + +--connection node_1 +ROLLBACK; + +--connection node_2 +SET SESSION wsrep_sync_wait = 0; +--let $wsrep_provider_options_node_2 = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'wsrep_provider_options'` +SET GLOBAL wsrep_provider_options = 'repl.causal_read_timeout=PT10M'; +SET SESSION wsrep_sync_wait = 7; + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +SELECT COUNT(*) = 0 FROM t1; + +--disable_query_log +--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_node_2'; + +--connection node_1 +SET SESSION wsrep_sync_wait = 0; +--let $wsrep_provider_options_node_1 = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'wsrep_provider_options'` +SET GLOBAL wsrep_provider_options = 'repl.causal_read_timeout=PT10M'; +SET SESSION wsrep_sync_wait = 7; + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +SELECT COUNT(*) = 0 FROM t1; + +--disable_query_log +--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_node_1'; + +DROP TABLE ten; +DROP TABLE t1; + +CALL mtr.add_suppression('InnoDB: Resizing redo log from'); +CALL mtr.add_suppression('InnoDB: Starting to delete and rewrite log files'); +CALL mtr.add_suppression('InnoDB: New log files created, LSN='); + diff --git a/mysql-test/suite/galera_sr/t/galera_sr_load_data.test b/mysql-test/suite/galera_sr/t/galera_sr_load_data.test new file mode 100644 index 00000000000..b430ace5d69 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_load_data.test @@ -0,0 +1,39 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test Streaming Replication + LOAD DATA +# + +--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size` +SET SESSION wsrep_trx_fragment_size = 512; + +# Create a file for LOAD DATA with 20K entries +--perl +open(FILE, ">", "$ENV{'MYSQLTEST_VARDIR'}/tmp/galera_sr_load_data.csv") or die; +foreach my $i (1..20000) { + print FILE "$i\n"; +} +EOF + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +# Record wsrep_last_committed as it was before LOAD DATA +--connection node_2 +--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` + +--connection node_1 +--disable_query_log +--eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/galera_sr_load_data.csv' INTO TABLE t1; +--enable_query_log + +--connection node_2 +--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` + +SELECT COUNT(*) = 20000 FROM t1; +# LOAD-ing 20K rows causes 3 commits to be registered +--disable_query_log +--eval SELECT $wsrep_last_committed_after - $wsrep_last_committed_before = 3 AS wsrep_last_committed_diff; +--enable_query_log + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_load_data_splitting.test b/mysql-test/suite/galera_sr/t/galera_sr_load_data_splitting.test new file mode 100644 index 00000000000..40e63e7c67f --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_load_data_splitting.test @@ -0,0 +1,50 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/big_test.inc + +# +# Test Streaming Replication and LOAD DATA splitting operating at the same time +# + +--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size` +--let $wsrep_load_data_splitting_orig = `SELECT @@wsrep_load_data_splitting` + +SET SESSION wsrep_trx_fragment_size = 512; +SET GLOBAL wsrep_load_data_splitting = TRUE; + + +# Create a file for LOAD DATA with 95K entries +--perl +open(FILE, ">", "$ENV{'MYSQLTEST_VARDIR'}/tmp/galera_sr_load_data.csv") or die; +foreach my $i (1..95000) { + print FILE "$i\n"; +} +EOF + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +# Record wsrep_last_committed as it was before LOAD DATA +--connection node_2 +--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` + +--connection node_1 +--disable_query_log +--eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/galera_sr_load_data.csv' INTO TABLE t1; +--enable_query_log + +--connection node_2 +--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` + +SELECT COUNT(*) = 95000 FROM t1; + +# LOAD-ing 95K rows causes 10 'commits' to be registered +--disable_query_log +--eval SELECT $wsrep_last_committed_after - $wsrep_last_committed_before = 10 AS wsrep_last_committed_diff; +--enable_query_log + +--connection node_1 +--disable_query_log +--eval SET GLOBAL wsrep_load_data_splitting = $wsrep_load_data_splitting_orig; +--enable_query_log + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_log_bin-master.opt b/mysql-test/suite/galera_sr/t/galera_sr_log_bin-master.opt new file mode 100644 index 00000000000..03fcb5d040d --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_log_bin-master.opt @@ -0,0 +1 @@ +--log-slave-updates --log-bin diff --git a/mysql-test/suite/galera_sr/t/galera_sr_log_bin.test b/mysql-test/suite/galera_sr/t/galera_sr_log_bin.test new file mode 100644 index 00000000000..069b9f44591 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_log_bin.test @@ -0,0 +1,66 @@ +# +# Interleave SR and non-SR transactions and confirm that the binlog is in correct order +# + +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t3 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t4 (f1 INTEGER) ENGINE=InnoDB; + +--source include/galera_cluster.inc + +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +RESET MASTER; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t2 VALUES (1); + +--connection node_2 +RESET MASTER; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size = 1; +START TRANSACTION; +INSERT INTO t3 VALUES (1); + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t4 VALUES (1); + +--connection node_1 +INSERT INTO t1 VALUES (2); +COMMIT; + +--connection node_1a +INSERT INTO t2 VALUES (2); +COMMIT; + +--connection node_2 +INSERT INTO t3 VALUES (2); +COMMIT; +--connection node_2a +INSERT INTO t4 VALUES (2); +COMMIT; + +--connection node_1 +SELECT COUNT(*) = 2 FROM t4; + +--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/ +--replace_column 2 <Pos> 5 <End_log_pos> +SHOW BINLOG EVENTS IN '0.000001' FROM 120; + +--connection node_2 +SELECT COUNT(*) = 2 FROM t4; + +--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/ +--replace_column 2 <Pos> 5 <End_log_pos> +SHOW BINLOG EVENTS IN '0.000001' FROM 120; + +DROP TABLE t1,t2,t3,t4; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_many_fragments.test b/mysql-test/suite/galera_sr/t/galera_sr_many_fragments.test new file mode 100644 index 00000000000..b3bac7df059 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_many_fragments.test @@ -0,0 +1,53 @@ +# +# Test the replication and subsequent cleanup of a large number of small transaction fragments +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/big_test.inc + +CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(512)) ENGINE=InnoDB; + +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 (f2) SELECT REPEAT('x', 512) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5; + +--connection node_2 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 100000 FROM t1; + +--connection node_1 +ROLLBACK; + +--connection node_2 +SET SESSION wsrep_sync_wait = 0; +--let $wsrep_provider_options_node_2 = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'wsrep_provider_options'` +SET GLOBAL wsrep_provider_options = 'repl.causal_read_timeout=PT10M'; +SET SESSION wsrep_sync_wait = 7; + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +SELECT COUNT(*) = 0 FROM t1; + +--disable_query_log +--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_node_2'; + +--connection node_1 +SET SESSION wsrep_sync_wait = 0; +--let $wsrep_provider_options_node_1 = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'wsrep_provider_options'` +SET GLOBAL wsrep_provider_options = 'repl.causal_read_timeout=PT10M'; +SET SESSION wsrep_sync_wait = 7; + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +SELECT COUNT(*) = 0 FROM t1; + +--disable_query_log +--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_node_1'; + +DROP TABLE ten; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_myisam.test b/mysql-test/suite/galera_sr/t/galera_sr_myisam.test new file mode 100644 index 00000000000..b037f817610 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_myisam.test @@ -0,0 +1,29 @@ +# +# Test that the basic MyISAM replication works even with SR enabled +# We basically check that the data arrived on the slave and that there +# were no assertions. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +CREATE TABLE t1 (f1 TEXT) ENGINE=MyISAM; + +--let $wsrep_replicate_myisam_orig = `SELECT @@wsrep_replicate_myisam` + +SET SESSION wsrep_trx_fragment_size = 1; +SET GLOBAL wsrep_replicate_myisam = TRUE; + +INSERT INTO t1 VALUES (REPEAT('x', 65535)); + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; +SELECT LENGTH(f1) = 65535 FROM t1; + +DROP TABLE t1; + +--connection node_1 +--disable_query_log +--eval SET GLOBAL wsrep_replicate_myisam = $wsrep_replicate_myisam_orig; +--enable_query_log diff --git a/mysql-test/suite/galera_sr/t/galera_sr_mysqldump_sst.cnf b/mysql-test/suite/galera_sr/t/galera_sr_mysqldump_sst.cnf new file mode 100644 index 00000000000..574ae28b54a --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_mysqldump_sst.cnf @@ -0,0 +1,11 @@ +!include ../galera_2nodes.cnf + +# We do not set mysqldump-related SST options here because doing so on startup +# causes the first MTR connection to be forefully dropped by Galera, which in turn confuses MTR + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true' + +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=1;pc.ignore_sb=true' + diff --git a/mysql-test/suite/galera_sr/t/galera_sr_mysqldump_sst.test b/mysql-test/suite/galera_sr/t/galera_sr_mysqldump_sst.test new file mode 100644 index 00000000000..88249c22f7a --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_mysqldump_sst.test @@ -0,0 +1,79 @@ +# +# Test mysqldump SST on slave if SR transaction is in progress +# + +--source include/big_test.inc +--source include/galera_cluster.inc + +--source suite/galera/include/galera_sst_set_mysqldump.inc + +--connection node_1 +CREATE TABLE ten (f1 INTEGER); +INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB; + +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size = 1000; +START TRANSACTION; +# Insert 1000 rows +INSERT INTO t1 (f2) SELECT REPEAT('x', 255) FROM ten AS a1, ten AS a2, ten AS a3; + +# Update 1000 rows +UPDATE t1 SET f2 = REPEAT('y', 255); + +# Wait for SR replication to kick in +--connection node_2 +--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +--source include/wait_condition.inc + +# Restart node #2 + +--connection node_2 +--let $MYSQLD2_DATADIR = `SELECT @@datadir` + +--echo Shutting down server ... +--source include/shutdown_mysqld.inc + +# Force SST +--remove_file $MYSQLD2_DATADIR/grastate.dat + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +--connection node_2 +--echo Starting server ... +--let $start_mysqld_params = --wsrep_sst_auth=sst:sst --wsrep_sst_method=mysqldump --wsrep-sst-receive-address=127.0.0.1:$NODE_MYPORT_2 +--source include/start_mysqld.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +# Check that node #2 is caught up with the SR transaction that is still in progress +--connection node_2 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1; +--source include/wait_condition.inc + +# Finalize transaction +--connection node_1 +UPDATE t1 SET f2 = REPEAT('z', 255); +COMMIT; + +# Confirm proper replication of entire transaction to node #2 +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SELECT COUNT(*) = 1000 FROM t1; +SELECT COUNT(*) = 1000 FROM t1 WHERE f2 = REPEAT('z', 255); + +DROP TABLE t1; +DROP TABLE ten; + +--connection node_1 +# galera_sst_restore.inc uses DROP USER internally which is incompatible +# with SR, need to disable SR before that. +SET SESSION wsrep_trx_fragment_size=0; +--source suite/galera/include/galera_sst_restore.inc diff --git a/mysql-test/suite/galera_sr/t/galera_sr_parallel_apply.test b/mysql-test/suite/galera_sr/t/galera_sr_parallel_apply.test new file mode 100644 index 00000000000..83a7acbe3e0 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_parallel_apply.test @@ -0,0 +1,59 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test SR with parallel apply +# + +--connection node_2 +--let $wsrep_slave_threads_orig = `SELECT @@wsrep_slave_threads` +SET GLOBAL wsrep_slave_threads = 5; + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 INTEGER) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f2) VALUES (1); +INSERT INTO t1 (f2) VALUES (1); +INSERT INTO t1 (f2) VALUES (1); +INSERT INTO t1 (f2) VALUES (1); +--send INSERT INTO t1 (f2) VALUES (1); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f2) VALUES (2); +INSERT INTO t1 (f2) VALUES (2); +INSERT INTO t1 (f2) VALUES (2); +INSERT INTO t1 (f2) VALUES (2); +--send INSERT INTO t1 (f2) VALUES (2); + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1 WHERE f2 = 1; +--source include/wait_condition.inc + +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1 WHERE f2 = 2; +--source include/wait_condition.inc + +--connection node_1 +--reap +COMMIT; + +--connection node_1a +--reap +ROLLBACK; + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SELECT COUNT(*) = 5 FROM t1; + +--connection node_1 +DROP TABLE t1; + +--connection node_2 +--disable_query_log +--eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig; +--enable_query_log diff --git a/mysql-test/suite/galera_sr/t/galera_sr_rollback.test b/mysql-test/suite/galera_sr/t/galera_sr_rollback.test new file mode 100644 index 00000000000..33a318f8ae3 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_rollback.test @@ -0,0 +1,76 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test that ROLLBACK works correctly with streaming replication +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1, 'a'); +INSERT INTO t1 VALUES (2, 'a'); +INSERT INTO t1 VALUES (3, 'a'); +INSERT INTO t1 VALUES (4, 'a'); +INSERT INTO t1 VALUES (5, 'a'); + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +INSERT INTO t1 VALUES (11, 'b'); +INSERT INTO t1 VALUES (12, 'b'); +INSERT INTO t1 VALUES (13, 'b'); +INSERT INTO t1 VALUES (14, 'b'); +INSERT INTO t1 VALUES (15, 'b'); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) >= 0 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +ROLLBACK; + +# +# After ROLLBACK, the table on node #2 should be empty +# + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 0 FROM t1; +--source include/wait_condition.inc + +# +# It should be possible to re-insert the values we just rolled back +# + +--connection node_1 +START TRANSACTION; +INSERT INTO t1 VALUES (1, 'a'); +INSERT INTO t1 VALUES (2, 'a'); +INSERT INTO t1 VALUES (3, 'a'); +INSERT INTO t1 VALUES (4, 'a'); +INSERT INTO t1 VALUES (5, 'a'); + +INSERT INTO t1 VALUES (11, 'b'); +INSERT INTO t1 VALUES (12, 'b'); +INSERT INTO t1 VALUES (13, 'b'); +INSERT INTO t1 VALUES (14, 'b'); +INSERT INTO t1 VALUES (15, 'b'); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) >= 9 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +COMMIT; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) >= 10 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_rollback_retry.test b/mysql-test/suite/galera_sr/t/galera_sr_rollback_retry.test new file mode 100644 index 00000000000..c6c443a0828 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_rollback_retry.test @@ -0,0 +1,55 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test that a SR transaction that was just ROLLBACKed on one node can be +# run against another node without any conflicts +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size` +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +ROLLBACK; + +# +# After ROLLBACK, the table on node #2 should be empty +# + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 0 FROM t1; +--source include/wait_condition.inc + +# +# It should be possible to reissue the same transaction against node #2 +# + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +COMMIT; + +SELECT COUNT(*) = 5 FROM t1; + +--connection node_1 +SELECT COUNT(*) = 5 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_rollback_savepoint.test b/mysql-test/suite/galera_sr/t/galera_sr_rollback_savepoint.test new file mode 100644 index 00000000000..93ff7a948c4 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_rollback_savepoint.test @@ -0,0 +1,51 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test that ROLLBACK TO SAVEPOINT works correctly with streaming replication +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1, 'a'); +INSERT INTO t1 VALUES (2, 'a'); +INSERT INTO t1 VALUES (3, 'a'); +INSERT INTO t1 VALUES (4, 'a'); +INSERT INTO t1 VALUES (5, 'a'); +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +SAVEPOINT s1; +INSERT INTO t1 VALUES (11, 'b'); +INSERT INTO t1 VALUES (12, 'b'); +INSERT INTO t1 VALUES (13, 'b'); +INSERT INTO t1 VALUES (14, 'b'); +INSERT INTO t1 VALUES (15, 'b'); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) > 5 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +ROLLBACK TO SAVEPOINT s1; + +INSERT INTO t1 VALUES (21, 'c'); +INSERT INTO t1 VALUES (22, 'c'); +INSERT INTO t1 VALUES (23, 'c'); +INSERT INTO t1 VALUES (24, 'c'); +INSERT INTO t1 VALUES (25, 'c'); + +--connection node_2 +SELECT COUNT(*) = 5 FROM t1 WHERE f2 = 'a'; +SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'b'; +SELECT COUNT(*) = 5 FROM t1 WHERE f2 = 'c'; + +--connection node_1 +COMMIT; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_rollback_statement.test b/mysql-test/suite/galera_sr/t/galera_sr_rollback_statement.test new file mode 100644 index 00000000000..74350faf5a2 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_rollback_statement.test @@ -0,0 +1,61 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test the case where a statement is rolled back due to an error while Streaming Replication +# is in effect. We construct an INSERT ... SELECT statement that will fail with a duplicate +# key error towards the end of the statement, after a portion has already been replicated via SR. +# + +--disable_query_log +--let $auto_increment_offset_orig = `SELECT @@auto_increment_offset` +SET GLOBAL auto_increment_offset=1; +--enable_query_log + +--connection node_1 +CREATE TABLE ten (f1 INTEGER); +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) ENGINE=InnoDB; + +INSERT INTO t1 (f2) SELECT REPEAT('a', 255) FROM ten AS a1, ten AS a2, ten AS a3; +ALTER TABLE t1 CHANGE f1 f1 INTEGER; +ALTER TABLE t1 DROP PRIMARY KEY; + +# This poison value is used to cause the INSERT ... SELECT below to fail +INSERT INTO t1 VALUES (1, 'abc'); + + +--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size` +SET SESSION wsrep_trx_fragment_size = 1; + +--error ER_DUP_ENTRY +INSERT INTO t2 SELECT * FROM t1; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 0 FROM t2; +--source include/wait_condition.inc + +# Cluster continues to operate after the implicit ROLLBACK; +--connection node_1 +INSERT INTO t2 VALUES (1, 'abc'); + +--connection node_2 +INSERT INTO t2 VALUES (2, 'abc'); + +--connection node_1 +SELECT COUNT(*) = 2 FROM t2; + +--connection node_2 +SELECT COUNT(*) = 2 FROM t2; + +--connection node_1 + +--disable_query_log +--eval SET GLOBAL auto_increment_offset=$auto_increment_offset_orig; +--enable_query_log + +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE ten; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_sbr.test b/mysql-test/suite/galera_sr/t/galera_sr_sbr.test new file mode 100644 index 00000000000..a24a520af60 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_sbr.test @@ -0,0 +1,31 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test that SR does not assert in the presence of statement-based replication events +# + +--connection node_1 +CREATE TABLE t1 (id INT) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 1; +SET SESSION BINLOG_FORMAT='STATEMENT'; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connection node_2 +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +COMMIT; + +--connection node_2 +SELECT COUNT(*) = 5 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_shutdown_master.test b/mysql-test/suite/galera_sr/t/galera_sr_shutdown_master.test new file mode 100644 index 00000000000..721f1dec06d --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_shutdown_master.test @@ -0,0 +1,45 @@ +# +# Shut down master (node #2) while an SR transaction is in progress +# + +--source include/galera_cluster.inc + +--connection node_2 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE = InnoDB; + +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; + +INSERT INTO t1 VALUES (1),(2),(3); + +--connection node_1 +--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +--source include/wait_condition.inc + +--connection node_2 +--source include/shutdown_mysqld.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + +# Confirm that SR table on slave is empty +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +SELECT COUNT(*) = 0 FROM t1; + +--connection node_2 +--source include/start_mysqld.inc + +# SR table on master should be empty too +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +# Confirm that the INSERT can be re-issued +INSERT INTO t1 VALUES (1),(2),(3); + +--connection node_1 +SELECT COUNT(*) = 3 FROM t1; + +DROP TABLE t1; + +--connection node_2 +CALL mtr.add_suppression("WSREP: failed to send SR rollback for ");
\ No newline at end of file diff --git a/mysql-test/suite/galera_sr/t/galera_sr_shutdown_slave.test b/mysql-test/suite/galera_sr/t/galera_sr_shutdown_slave.test new file mode 100644 index 00000000000..53f6fd7885c --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_shutdown_slave.test @@ -0,0 +1,63 @@ +# +# Shut down slave (node #2) while an SR transaction is in progress +# + +--source include/galera_cluster.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE = InnoDB; + +# We start two transactions on the master so that we can commit one while the slave +# is down and commit the other after the slave has rejoined + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES (11),(12),(13); + +--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1b +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES (21),(22),(23); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +--source include/wait_condition.inc + +--source include/shutdown_mysqld.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + +# Commit one transaction while the slave is down +--connection node_1a +INSERT INTO t1 VALUES (14),(15),(16); +COMMIT; + +# Restart slave +--connection node_2 +--source include/start_mysqld.inc + +# Confirm SR table on slave has entries +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; +SELECT COUNT(*) = 6 FROM t1 WHERE f1 IN (11,12,13,14,15,16); + +# Commit the second transaction on master after the slave has rejoined +--connection node_1b +INSERT INTO t1 VALUES (24),(25),(26); +COMMIT; + +# Confirm that SR table on slave is empty +--connection node_2 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +SELECT COUNT(*) = 12 FROM t1; + +# SR table on master should be empty too +--connection node_1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_small_gcache.cnf b/mysql-test/suite/galera_sr/t/galera_sr_small_gcache.cnf new file mode 100644 index 00000000000..c8e17436e71 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_small_gcache.cnf @@ -0,0 +1,6 @@ +!include ../galera_2nodes.cnf +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=16K' +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=16K' + diff --git a/mysql-test/suite/galera_sr/t/galera_sr_small_gcache.test b/mysql-test/suite/galera_sr/t/galera_sr_small_gcache.test new file mode 100644 index 00000000000..403b44286d9 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_small_gcache.test @@ -0,0 +1,21 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# A simple test with a very low value for gcache.size - 16K +# + +--connection node_1 +CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); + +SET SESSION wsrep_trx_fragment_size = 1; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; + +--connection node_2 +SELECT COUNT(*) = 10000 FROM t1; + +--connection node_1 +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_table_contents.test b/mysql-test/suite/galera_sr/t/galera_sr_table_contents.test new file mode 100644 index 00000000000..92d29fe4ca2 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_table_contents.test @@ -0,0 +1,49 @@ +# +# This test dumps the contents of the SR table under various circumstances +# + +--source include/galera_cluster.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3); + +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3); + +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +--echo +--echo Start of Simple Insert +INSERT INTO t1 VALUES (4); +--source suite/galera/include/galera_dump_sr_table.inc +--echo End of Simple Insert +--echo +ROLLBACK; + +--echo Start of Multi-row Update +UPDATE t1 SET f1 = f1 + 10; +--source suite/galera/include/galera_dump_sr_table.inc +--echo End of Multi-row Update +--echo +ROLLBACK; + +--echo Start of Multi-table Update +UPDATE t1, t2 SET t1.f1 = t1.f1 + 100, t2.f1 = t2.f1 + 100; +--source suite/galera/include/galera_dump_sr_table.inc +--echo End of Multi-table Update +--echo +ROLLBACK; + +--echo Start of Savepoint +INSERT INTO t1 VALUES (1000); +SAVEPOINT X; +INSERT INTO t1 VALUES (2000); +ROLLBACK TO SAVEPOINT X; +--source suite/galera/include/galera_dump_sr_table.inc +--echo End of Savepoint +--echo +ROLLBACK; + +DROP TABLE t1, t2; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_transaction_replay.test b/mysql-test/suite/galera_sr/t/galera_sr_transaction_replay.test new file mode 100644 index 00000000000..ca20dcdde24 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_transaction_replay.test @@ -0,0 +1,260 @@ +# +# This test tests the operation of SR transaction replay. If a +# potentially conflicting remote transaction arrives at +# just the right time during the commit of a local transaction, +# the local transaction will be aborted and replayed. +# +# This test is divided in two sections: +# 1) Test the scenario where the last fragment does not have write set +# payload, just commit flag is replicated +# 2) Test the scenario where the last fragment has write set payload +# and commit flag + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc +--source include/galera_have_debug_sync.inc + +# Control connection for manipulating galera sync points +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET SESSION wsrep_sync_wait = 0; + +--connection node_1 + +--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'` + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)); + +######################################################################### +# +# 1) Replay without commit fragment write set payload +# +######################################################################### + +INSERT INTO t1 VALUES (1, 'a'); +INSERT INTO t1 VALUES (2, 'a'); + +--connection node_1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 1; +START TRANSACTION; + +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE; + +# +# Block the commit from node_2 +# +--connection node_1a +--let $galera_sync_point = apply_monitor_slave_enter_sync +--source include/galera_set_sync_point.inc + +# +# Issue conflicting UPDATE from node_2 and wait until it hits the +# apply monitor (but does not apply yet) +# +--connection node_2 +UPDATE t1 SET f2 = 'c' WHERE f1 = 2; + +--connection node_1a +--let $galera_sync_point = apply_monitor_slave_enter_sync +--source include/galera_wait_sync_point.inc + +# +# Set a new sync point to block in local monitor on node_1 commit +# +--source include/galera_clear_sync_point.inc +--let $galera_sync_point = local_monitor_master_enter_sync +--source include/galera_set_sync_point.inc + +# +# Send the commit on node_1 +# +--connection node_1 +--send COMMIT + +# +# Wait until commit reaches sync point +# +--connection node_1a +SET SESSION wsrep_sync_wait = 0; +--let $galera_sync_point = apply_monitor_slave_enter_sync local_monitor_master_enter_sync +--source include/galera_wait_sync_point.inc + +# +# Release conflicting slave transaction and wait until it has BF +# aborted pending COMMIT +# +--source include/galera_clear_sync_point.inc +--let $galera_sync_point = abort_trx_end +--source include/galera_set_sync_point.inc + +--let $galera_sync_point = apply_monitor_slave_enter_sync +--source include/galera_signal_sync_point.inc + +--let $galera_sync_point = abort_trx_end local_monitor_master_enter_sync +--source include/galera_wait_sync_point.inc + +# +# Release both threads, local thread will now replay +# +--source include/galera_clear_sync_point.inc +--let $galera_sync_point = abort_trx_end +--source include/galera_signal_sync_point.inc + +--let $galera_sync_point = local_monitor_master_enter_sync +--source include/galera_signal_sync_point.inc + +# +# Commit must succeed +# +--connection node_1 +--reap + + +# +# Check the outcome and that wsrep schema SR table is empty +# +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b'; +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +# +# wsrep_local_replays has increased by 1 +# +--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'` +--disable_query_log +--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old = 1 AS wsrep_local_replays; +--enable_query_log + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b'; +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +DELETE FROM t1; + +######################################################################### +# +# 2) Replay with commit fragment write set payload +# +######################################################################### + +INSERT INTO t1 VALUES (1, 'a'); +INSERT INTO t1 VALUES (2, 'a'); + +--connection node_1 +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 1; +START TRANSACTION; + +# +# Do first update SR on +# +UPDATE t1 SET f2 = 'x' WHERE f1 = 1; + +# +# Disable SR for following statements +# +SET SESSION wsrep_trx_fragment_size = 0; + +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE; + +# +# Block the commit from node_2 +# +--connection node_1a +--let $galera_sync_point = apply_monitor_slave_enter_sync +--source include/galera_set_sync_point.inc + +# +# Issue conflicting UPDATE from node_2 and wait until it hits the +# apply monitor (but does not apply yet) +# +--connection node_2 +UPDATE t1 SET f2 = 'c' WHERE f1 = 2; + +--connection node_1a +--let $galera_sync_point = apply_monitor_slave_enter_sync +--source include/galera_wait_sync_point.inc + +# +# Set a new sync point to block in local monitor on node_1 commit +# +--source include/galera_clear_sync_point.inc +--let $galera_sync_point = local_monitor_master_enter_sync +--source include/galera_set_sync_point.inc + +# +# Send the commit on node_1 +# +--connection node_1 +--send COMMIT + +# +# Wait until commit reaches sync point +# +--connection node_1a +SET SESSION wsrep_sync_wait = 0; +--let $galera_sync_point = apply_monitor_slave_enter_sync local_monitor_master_enter_sync +--source include/galera_wait_sync_point.inc + +# +# Release conflicting slave transaction and wait until it has BF +# aborted pending COMMIT +# +--source include/galera_clear_sync_point.inc +--let $galera_sync_point = abort_trx_end +--source include/galera_set_sync_point.inc + +--let $galera_sync_point = apply_monitor_slave_enter_sync +--source include/galera_signal_sync_point.inc + +--let $galera_sync_point = abort_trx_end local_monitor_master_enter_sync +--source include/galera_wait_sync_point.inc + +# +# Release both threads, local thread will now replay +# +--source include/galera_clear_sync_point.inc +--let $galera_sync_point = abort_trx_end +--source include/galera_signal_sync_point.inc + +--let $galera_sync_point = local_monitor_master_enter_sync +--source include/galera_signal_sync_point.inc + +# +# Commit must succeed +# +--connection node_1 +--reap + + +# +# Check the outcome and that wsrep schema SR table is empty +# +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b'; +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +# +# wsrep_local_replays has increased by 1 +# +--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'` +--disable_query_log +--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old = 2 AS wsrep_local_replays; +--enable_query_log + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b'; +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +DELETE FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_unit_statements.test b/mysql-test/suite/galera_sr/t/galera_sr_unit_statements.test new file mode 100644 index 00000000000..390d4c73ac1 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_unit_statements.test @@ -0,0 +1,47 @@ +# +# Test wsrep_fragment_unit = statements +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +SET SESSION wsrep_trx_fragment_size = 3; +SET SESSION wsrep_trx_fragment_unit = 'statements'; + +--connection node_1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); + +# The table count on the slave should jump from 0 +--connection node_2 +--sleep 1 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; + +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +# to 3 +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) = 3 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +INSERT INTO t1 VALUES (6); + +# and then to to 6 +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 6 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +COMMIT; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_v1_row_events-master.opt b/mysql-test/suite/galera_sr/t/galera_sr_v1_row_events-master.opt new file mode 100644 index 00000000000..0b5f8bf7104 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_v1_row_events-master.opt @@ -0,0 +1 @@ +--log-bin-use-v1-row-events=1 --wsrep-trx-fragment-size=1 diff --git a/mysql-test/suite/galera_sr/t/galera_sr_v1_row_events.test b/mysql-test/suite/galera_sr/t/galera_sr_v1_row_events.test new file mode 100644 index 00000000000..d3d4d2d0c14 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_v1_row_events.test @@ -0,0 +1,27 @@ +# +# Test that Galera SR continues to run even with --log-bin-use-v1-row-events=1 +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 1 FROM t1; + +--connection node_1 +COMMIT; + +SET AUTOCOMMIT=ON; +UPDATE t1 SET f1 = 2 WHERE f1 = 1; + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_ws_size.test b/mysql-test/suite/galera_sr/t/galera_sr_ws_size.test new file mode 100644 index 00000000000..98f6e796ef6 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_ws_size.test @@ -0,0 +1,70 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test that SR transaction is cumulatively allowed to grow beyond repl.max_ws_size +# if individual fragements are below that size +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(254)) ENGINE=InnoDB; +CREATE TABLE ten (f1 INTEGER); +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); + +--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size` +--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options` + +SET SESSION wsrep_trx_fragment_size = 512; +SET GLOBAL wsrep_provider_options='repl.max_ws_size=4096'; + +# +# Create a transaction larger than repl.max_ws_size +# + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1; +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1; +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1; +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1; +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1; + +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1; +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1; +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1; +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1; +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1; + +# +# We expect that the transaction can proceed successfully +# + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 10 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +# Commit succeeds +COMMIT; + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +SELECT COUNT(*) = 100 FROM t1; + +# +# Cleanup +# + +DROP TABLE t1; +DROP TABLE ten; + +--connection node_1 +--disable_query_log +--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_orig'; +--enable_query_log + +call mtr.add_suppression('WSREP: transaction size limit.*'); +call mtr.add_suppression('WSREP: rbr write fail.*'); +call mtr.add_suppression('WSREP: Maximum writeset size exceeded by.*'); +call mtr.add_suppression('WSREP: transaction size exceeded.*'); diff --git a/mysql-test/suite/galera_sr/t/galera_sr_ws_size2.test b/mysql-test/suite/galera_sr/t/galera_sr_ws_size2.test new file mode 100644 index 00000000000..2b9bc4819b8 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_ws_size2.test @@ -0,0 +1,62 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test that if wsrep_trx_fragment_size > repl.max_ws_size, no SR takes place and +# the transaction is properly aborted. +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(254)) ENGINE=InnoDB; +CREATE TABLE ten (f1 INTEGER); +INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); + +--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size` +--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options` + +SET SESSION wsrep_trx_fragment_size = 256; +SET GLOBAL wsrep_provider_options='repl.max_ws_size=128'; + +# +# Create a transaction larger than repl.max_ws_size +# + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +--error ER_ERROR_DURING_COMMIT,ER_ERROR_ON_WRITE,ER_BINLOG_ROW_LOGGING_FAILED +INSERT INTO t1 (f2) SELECT REPEAT('x', 254) FROM ten AS a1, ten AS a2; + +# +# We expect that the transaction can not complete successfully +# + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--sleep 2 +SELECT COUNT(*) = 0 FROM t1; + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +SELECT COUNT(*) = 0 FROM t1; + +# +# Cleanup +# +--connection node_1 +--disable_query_log +--eval SET GLOBAL wsrep_trx_fragment_size = $wsrep_trx_fragment_size_orig; +--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_orig'; +--enable_query_log + +DROP TABLE t1; +DROP TABLE ten; + +call mtr.add_suppression('WSREP: SR rollback replication failure.*'); +call mtr.add_suppression('WSREP: transaction size limit.*'); +call mtr.add_suppression('WSREP: SR rbr write fail.*'); +call mtr.add_suppression('WSREP: Maximum writeset size exceeded by.*'); +call mtr.add_suppression('WSREP: transaction size exceeded.*'); +call mtr.add_suppression('WSREP: fragment replication failed:'); +call mtr.add_suppression('WSREP: post commit failed for SR rollback'); +call mtr.add_suppression('WSREP: pre_commit for SR rollback returned 2, thd:*'); +call mtr.add_suppression('WSREP: wsrep_rollback failed to send SR ROLLBACK for *'); diff --git a/mysql-test/suite/galera_sr/t/galera_var_ignore_apply_errors_sr.test b/mysql-test/suite/galera_sr/t/galera_var_ignore_apply_errors_sr.test new file mode 100644 index 00000000000..8b8d7197c1c --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_var_ignore_apply_errors_sr.test @@ -0,0 +1,37 @@ +# +# Test option wsrep_ignore_apply_errors +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Delete row that does not exist using SR transaction +# + +--connection node_2 +SET GLOBAL wsrep_ignore_apply_errors = 2; + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER); +INSERT INTO t1 VALUES (2); +SET GLOBAL wsrep_on = OFF; +INSERT INTO t1 VALUES (1); +SET GLOBAL wsrep_on = ON; +SET SESSION wsrep_trx_fragment_size = 1; +START TRANSACTION; +INSERT INTO t1 VALUES (3); +DELETE FROM t1 WHERE f1 = 1; +DELETE FROM t1 WHERE f1 = 2; +COMMIT; + +--connection node_1 +SELECT COUNT(*) = 1 FROM t1; +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; + +SET SESSION wsrep_trx_fragment_size = 0; +DROP TABLE t1; + +SET GLOBAL wsrep_ignore_apply_errors = 7; +CALL mtr.add_suppression("Slave SQL: Could not execute Delete_rows event"); diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep#215.test b/mysql-test/suite/galera_sr/t/mysql-wsrep#215.test new file mode 100644 index 00000000000..45c2b9514df --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep#215.test @@ -0,0 +1,161 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test the following sequence of events: +# +# 1. Node #1 begins a transaction +# 2. Node #2 performs a conflicting insert +# 3. Node #1 attempts to SR-replicate a conflicting transaction +# + +# to sync node_1 appliers +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 2; +SET SESSION wsrep_trx_fragment_unit = 'statements'; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +# +# processlist is good to see manually that applier reached sync point +# but is not deterministic in testing, commenting out +# SHOW PROCESSLIST; +--connection node_1a +SET GLOBAL debug = 'd,sync.wsrep_apply_cb'; +SET SESSION wsrep_sync_wait = 0; + +--connection node_2 +INSERT INTO t1 VALUES (1); + +--connection node_1 +# +# TODO: check here that applier is parked in the sync point +# +SELECT COUNT(*) = 0 FROM t1; +INSERT INTO t1 VALUES (1); + +--connection node_1a +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; +SET GLOBAL debug = ''; + +--connection node_1 +--error ER_LOCK_DEADLOCK,ER_QUERY_INTERRUPTED +INSERT INTO t1 VALUES (2); + +COMMIT; + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +# +# Similar test with BYTES unit +# +--connection node_1 +TRUNCATE TABLE t1; + +SET SESSION wsrep_trx_fragment_size = 10; +SET SESSION wsrep_trx_fragment_unit = 'bytes'; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +--connection node_1a +SET GLOBAL debug = 'd,sync.wsrep_apply_cb'; +SET SESSION wsrep_sync_wait = 0; + +--connection node_2 +INSERT INTO t1 VALUES (1); + +--connection node_1 +SELECT COUNT(*) = 0 FROM t1; +--send INSERT INTO t1 VALUES (1) +# +# WHY sleep here? +# without this sleep, applier would be released with following signal +# and applier would have chance to BF abort the SR trx. +# We don't want this to happen, but instead let the SR trx to replicate +# and notice the certification failure. +# TODO: sleep is not good, this should be refactored somehow to guarantee +# correct order for cert failure vs BF abort +# +--sleep 2 + +--connection node_1a +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; +SET GLOBAL debug = ''; + +--connection node_1 +--error ER_LOCK_DEADLOCK +--reap +INSERT INTO t1 VALUES (2); +COMMIT; + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_2 +SELECT COUNT(*) = 2 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + + +# +# One more test with BYTES unit, but now fragment size is adjusted so +# that second insert should trigger fragment replication. +# Currently 200 bytes is good choice here, but this may change with +# future MySQL versions. +# => If this test fails after some MySQL merge, check if frgament size +# needs to be tuned to spot at second insert statement. +# +--connection node_1 +TRUNCATE TABLE t1; + +SET SESSION wsrep_trx_fragment_size = 200; +SET SESSION wsrep_trx_fragment_unit = 'bytes'; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +SET GLOBAL debug = 'd,sync.wsrep_apply_cb'; +SET SESSION wsrep_sync_wait = 0; + +--connection node_2 +INSERT INTO t1 VALUES (1); + +--connection node_1 +SELECT COUNT(*) = 0 FROM t1; + +INSERT INTO t1 VALUES (1); + +--send INSERT INTO t1 VALUES (2) +# +# WHY sleep here? +# See above comment, same reason here +# +--sleep 2 + +--connection node_1a +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; +SET GLOBAL debug = ''; + +--connection node_1 +--error ER_LOCK_DEADLOCK +--reap +COMMIT; + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#136-master.opt b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#136-master.opt new file mode 100644 index 00000000000..03fcb5d040d --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#136-master.opt @@ -0,0 +1 @@ +--log-slave-updates --log-bin diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#136.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#136.test new file mode 100644 index 00000000000..96736889cd5 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#136.test @@ -0,0 +1,37 @@ +# SR transactions are not binlogged #136 + +--source include/galera_cluster.inc + +--connection node_1 +RESET MASTER; + +--connection node_2 +RESET MASTER; + +--connection node_1 +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +COMMIT; + +SET SESSION wsrep_trx_fragment_size = 0; +INSERT INTO t1 VALUES (3),(4); +COMMIT; + +--connection node_1 +--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/ +--replace_column 2 <Pos> 5 <End_log_pos> +SHOW BINLOG EVENTS IN '0.000001' FROM 120; + +--connection node_2 +# Wait for all updates to arrive before dumping binlog +SELECT COUNT(*) = 4 FROM t1; + +--replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/ +--replace_column 2 <Pos> 5 <End_log_pos> +SHOW BINLOG EVENTS IN '0.000001' FROM 120; + +--connection node_1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#138.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#138.test new file mode 100644 index 00000000000..2e67e730f79 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#138.test @@ -0,0 +1,25 @@ +# SR: two identical transactions have different value for the WSREP_FLAG_PA_UNSAFE flag + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); + +--connection node_2 +SELECT flags FROM wsrep_schema.SR; + +--connection node_1 +ROLLBACK; +INSERT INTO t1 VALUES (3),(4); + +--connection node_2 +SELECT flags FROM wsrep_schema.SR; + +--connection node_1 +ROLLBACK; +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#14.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#14.test new file mode 100644 index 00000000000..deeb890fa0b --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#14.test @@ -0,0 +1,21 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; + +SET SESSION wsrep_trx_fragment_size = 1; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); + +COMMIT; + +DROP TABLE t1; + +--connection node_2 +--source include/galera_wait_ready.inc + diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#148.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#148.test new file mode 100644 index 00000000000..5210b9ce99e --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#148.test @@ -0,0 +1,60 @@ +# statement rollback for SR transaction causes slave crash for inconsistency + +# We test the following: +# 1. Create a transaction that is blocked by an SR transaction +# 2. Force the SR transaction to have a statement rollback +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t2 VALUES (6),(7),(8),(9),(10),(1); + +--connection node_2 +SET GLOBAL wsrep_slave_threads = 2; +SET GLOBAL DEBUG = 'd,sync.wsrep_apply_cb'; + +# Begin SR transaction +--connection node_1 +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1), (2), (3), (4), (5); + +# Begin non-SR transaction that will block waiting for the SR transaction +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +SET AUTOCOMMIT=OFF; +START TRANSACTION; +--send INSERT INTO t1 VALUES (1), (2), (3), (4), (5); + +# Cause the SR transaction to fail with a duplicate key error +--connection node_1 +--send INSERT INTO t1 SELECT * FROM t2; + +# Continue and commit the non-SR transaction. +--connection node_1a +--reap +INSERT INTO t1 VALUES (6), (7), (8), (9), (10); +COMMIT; + +--connection node_1 +--error ER_LOCK_DEADLOCK,ER_DUP_ENTRY +--reap + +--connection node_2 +SET GLOBAL wsrep_slave_threads = 1; +SET GLOBAL DEBUG = ''; +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; + +SELECT COUNT(*) = 10 FROM t1; + +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#15.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#15.test new file mode 100644 index 00000000000..4aaff058b30 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#15.test @@ -0,0 +1,17 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +CREATE TABLE t1 (id INT) ENGINE=InnoDB; + +SET SESSION wsrep_trx_fragment_size = 1; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); + +COMMIT; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.inc b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.inc new file mode 100644 index 00000000000..29755ab6c2e --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.inc @@ -0,0 +1,104 @@ +# --source include/galera_cluster.inc +# --source include/have_debug_sync.inc + +# +# This test attempts to catch a race condition between autocommit +# transaction and transaction which is rolling back due to +# deadlock. +# +# Test outline: +# * Trx 1a makes updates +# * SR trx 1b writes a row 3, then makes updates +# * AC trx 1c will attempt to write row 3 and will wait for lock +# held by 1b +# * Sync point is set for 1b to delay SR rollback +# * SR trx 1b makes an update which makes it conflict with trx 1a +# * Slave shows BF - BF conflict and fails in applying write event + +--connection node_1 + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 VARCHAR(1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, 'x'), (2, 'x'), (4, 'x'), (5, 'x'); + +# --connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +# --connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1 +# --connect node_1c, 127.0.0.1, root, , test, $NODE_MYPORT_1 + +--connection node_1a +START TRANSACTION; + +UPDATE t1 SET f2 = 'a' WHERE f1 = 1; +UPDATE t1 SET f2 = 'a' WHERE f1 = 4; +UPDATE t1 SET f2 = 'a' WHERE f1 = 5; + + +--connection node_1b +START TRANSACTION; +SET SESSION wsrep_trx_fragment_size = 1; +INSERT INTO t1 VALUES (3, 'b'); +UPDATE t1 SET f2 = 'b' WHERE f1 = 2; + +--connection node_2 +SELECT * FROM t1; + +# Will block, waiting for 1b +--connection node_1c +SET AUTOCOMMIT=ON; +--send INSERT INTO t1 VALUES (3, 'c') + +--connection node_2 +SELECT * FROM t1; + +# Will block, waiting for 1b +--connection node_1a +--send UPDATE t1 SET f2 = 'a' WHERE f1 = 2 + +# Will deadlock +--connection node_1b +SET DEBUG_SYNC = 'wsrep_before_SR_rollback SIGNAL wait WAIT_FOR continue'; +--send UPDATE t1 SET f2 = 'b' WHERE f1 = 1 + +# Wait until 1b hits rollback +--connection node_1 +SET DEBUG_SYNC = 'now WAIT_FOR wait'; + +# UPDATE 12.06.2016: as of recent wsrep API changes, rollbacking thread no +# longer queues ROLLBACKs and blocks on ROLLBACK replication before performing +# the actual rollback. As a result this test is moot as both node_1a and node_1c +# connections are hanging now until sync point is released. Thus sync point +# release had to be moved above to release the connections. However it is not +# impossible that further changes in the code may reintroduce the race, so +# leaving the test as close to original as possible. +# +# --connection node_1a +# --reap +# COMMIT; +# +# --connection node_1c +# --reap +# +# UPDATE t1 SET f2 = 'x' WHERE f1 = 3; + +--connection node_1 +SET DEBUG_SYNC = 'now SIGNAL continue'; + +--connection node_1c +--reap + +UPDATE t1 SET f2 = 'x' WHERE f1 = 3; + +--connection node_1a +--reap +COMMIT; + +--connection node_1b +--error ER_LOCK_DEADLOCK +--reap + +--connection node_1 +SELECT * FROM t1; +--connection node_2 +SELECT * FROM t1; + +--connection node_1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.test new file mode 100644 index 00000000000..85d501288b0 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#165.test @@ -0,0 +1,41 @@ +--source include/galera_cluster.inc +--source include/have_debug_sync.inc + +# +# This test attempts to catch a race condition between autocommit +# transaction and transaction which is rolling back due to +# deadlock. +# +# Since it is trying to catch a race condition which may not reliably +# occur, several runs are necessary for certainty. Hence the body of +# the test was placed into the .inc file and sourced several times below +# +# Test outline: +# * Trx 1a makes updates +# * SR trx 1b writes a row 3, then makes updates +# * AC trx 1c will attempt to write row 3 and will wait for lock +# held by 1b +# * Sync point is set for 1b to delay SR rollback +# * SR trx 1b makes an update which makes it conflict with trx 1a +# * Slave shows BF - BF conflict and fails in applying write event + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connect node_1c, 127.0.0.1, root, , test, $NODE_MYPORT_1 + +--source mysql-wsrep-features#165.inc +--source mysql-wsrep-features#165.inc +--source mysql-wsrep-features#165.inc +--source mysql-wsrep-features#165.inc +--source mysql-wsrep-features#165.inc +--source mysql-wsrep-features#165.inc +--source mysql-wsrep-features#165.inc +--source mysql-wsrep-features#165.inc +--source mysql-wsrep-features#165.inc +--source mysql-wsrep-features#165.inc +--source mysql-wsrep-features#165.inc +--source mysql-wsrep-features#165.inc +--source mysql-wsrep-features#165.inc +--source mysql-wsrep-features#165.inc +--source mysql-wsrep-features#165.inc +--source mysql-wsrep-features#165.inc diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#213.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#213.test new file mode 100644 index 00000000000..99bbf505bf6 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#213.test @@ -0,0 +1,63 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test the effect of Cluster Configuration Change on a concurrently-running SR transaction +# We use SET GLOBAL wsrep_cluster_address = '' to cause the master (node_2) to temporarily +# leave the cluster. +# + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 + +--connection node_2 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size` +SET SESSION wsrep_trx_fragment_size = 1; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +--connection node_1 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +# +# Trigger CC . The transaction is aborted and we expect the SR tables to be cleaned up +# + +--connection node_2a +--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address` +SET GLOBAL wsrep_cluster_address = ''; +--sleep 2 + +--connection node_2 +# Changing wsrep_cluster_address causes the server to drop all other +# connections. Expect CR_SERVER_LOST error +--error 2013 +INSERT INTO t1 VALUES (6); + +--connection node_1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +# Restore cluster + +--connection node_2a +--disable_query_log +--eval SET GLOBAL wsrep_cluster_address='gcomm://127.0.0.1:$NODE_GALERAPORT_1'; +--enable_query_log +--sleep 2 + +--source include/galera_wait_ready.inc +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + + +DROP TABLE t1; + +CALL mtr.add_suppression("WSREP: failed to send SR rollback for "); diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#214.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#214.test new file mode 100644 index 00000000000..8c3dfb8b801 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#214.test @@ -0,0 +1,86 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test the effect of Cluster Configuration Change on a concurrently-running +# SR transaction. We use SET GLOBAL wsrep_cluster_address = '' to cause the +# slave (node_2) to temporarily leave the cluster. +# + +# Start with a clean slate +--connection node_2 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +--connection node_1 +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size` +SET SESSION wsrep_trx_fragment_size = 1; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +--connection node_2 +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +# +# Trigger CC . The transaction should be able to continue +# + +--connection node_2 +--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address` +SET GLOBAL wsrep_cluster_address = ''; +--sleep 2 + +--connection node_1 +# Continue generating events in the transaction + +INSERT INTO t1 VALUES (6); +INSERT INTO t1 VALUES (7); +INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (9); +INSERT INTO t1 VALUES (10); + +SELECT COUNT(*) > 0 FROM wsrep_schema.SR; + +# Restore cluster + +--connection node_2 +--disable_query_log +--eval SET GLOBAL wsrep_cluster_address='gcomm://127.0.0.1:$NODE_GALERAPORT_1'; +--enable_query_log +--sleep 2 +--source include/galera_wait_ready.inc + +# Confirm that the SR table still contains entries from ongoing transaction +SELECT count(*) > 0 FROM wsrep_schema.SR; + +# Continue and finalize transaction +--connection node_1 +INSERT INTO t1 VALUES (11); +INSERT INTO t1 VALUES (12); +INSERT INTO t1 VALUES (13); +INSERT INTO t1 VALUES (14); +INSERT INTO t1 VALUES (15); +COMMIT; + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +# Confirm that transaction was replicated properly +# and SR table is cleaned up afterwards. + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 15 FROM t1; +--source include/wait_condition.inc + +SELECT COUNT(*) = 0 FROM wsrep_schema.SR; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#22.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#22.test new file mode 100644 index 00000000000..544109dadee --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#22.test @@ -0,0 +1,47 @@ +# Assertion `total_length + thd->wsrep_fragment_base == saved_pos' failed in wsrep_write_cache_inc() with ROLLBACK TO SAVEPOINT and SR + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER, f2 VARCHAR(10)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size=1; +START TRANSACTION; +INSERT INTO t1 VALUES (1, 'a'); +INSERT INTO t1 VALUES (2, 'a'); +INSERT INTO t1 VALUES (3, 'a'); +INSERT INTO t1 VALUES (4, 'a'); +INSERT INTO t1 VALUES (5, 'a'); +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) = 5 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +SAVEPOINT s1; +INSERT INTO t1 VALUES (11, 'b'); +INSERT INTO t1 VALUES (12, 'b'); +INSERT INTO t1 VALUES (13, 'b'); +INSERT INTO t1 VALUES (14, 'b'); +INSERT INTO t1 VALUES (15, 'b'); + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 10 FROM t1; +--source include/wait_condition.inc + +--connection node_1 +ROLLBACK TO SAVEPOINT s1; + +INSERT INTO t1 VALUES (21, 'c'); + +COMMIT; + +--connection node_1 +SELECT COUNT(*) = 6 FROM t1; + + +--connection node_2 +SELECT COUNT(*) = 6 FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#27.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#27.test new file mode 100644 index 00000000000..f9c09391f8f --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#27.test @@ -0,0 +1,29 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +ALTER TABLE t1 ADD COLUMN f2 INTEGER; + +--connection node_2 +--sleep 2 +SET SESSION wsrep_sync_wait = 0; +SELECT COUNT(*) = 0 FROM t1; + +--connection node_1 +--error ER_LOCK_DEADLOCK +COMMIT; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#29.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#29.test new file mode 100644 index 00000000000..2349fe9979f --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#29.test @@ -0,0 +1,23 @@ +# +# mysql-wsrep-features#29 Unwarranted deadlock error with SR and a single-node cluster +# + +SET SESSION wsrep_trx_fragment_size = 1; +SET SESSION binlog_format = STATEMENT; + +create table t1 (id int not null, f_id int not null, f int not null, +primary key(f_id, id)) engine=innodb; + +create table t2 (id int not null,s_id int not null,s varchar(200), +primary key(id)) engine=innodb; + +INSERT INTO t1 VALUES (8, 1, 3); +INSERT INTO t1 VALUES (1, 2, 1); +INSERT INTO t2 VALUES (1, 0, ''); +INSERT INTO t2 VALUES (8, 1, ''); + +DELETE ml.* FROM t1 AS ml LEFT JOIN t2 AS mm ON (mm.id=ml.id) +WHERE mm.id IS NULL; + +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#32-master.opt b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#32-master.opt new file mode 100644 index 00000000000..a6ef074a120 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#32-master.opt @@ -0,0 +1 @@ +--innodb-lock-wait-timeout=1 diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#32.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#32.test new file mode 100644 index 00000000000..72c7a7b5e82 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#32.test @@ -0,0 +1,44 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# mysql-wsrep-features#32 Assertion `meta->gtid.seqno == wsrep_thd_trx_seqno(thd)' failed in wsrep_commit_cb with SR +# + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +SET SESSION wsrep_trx_fragment_size = 1; + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) > 0 FROM t1; +--source include/wait_condition.inc + +SET AUTOCOMMIT=OFF; + +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +START TRANSACTION; + +INSERT INTO t1 VALUES (9); +INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (7); +INSERT INTO t1 VALUES (6); + +--error ER_LOCK_WAIT_TIMEOUT +INSERT INTO t1 VALUES (5); +ROLLBACK; + +--connection node_1 +COMMIT; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#35.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#35.test new file mode 100644 index 00000000000..ec78747949f --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#35.test @@ -0,0 +1,46 @@ +--source include/have_debug_sync.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +# Block node #2's applier so that it is able to issue a conflicting INSERT before +# node #1 INSERTs have been applied on it. + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +SELECT COUNT(*) = 0 FROM t1; +SET SESSION wsrep_sync_wait = 0; +--let $debug_orig = `SELECT @@debug` +SET GLOBAL debug = 'd,sync.wsrep_apply_cb'; +SET SESSION wsrep_sync_wait = 0; + +--connection node_1 +--let $wsrep_trx_fragment_size_orig = `SELECT @@wsrep_trx_fragment_size` +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +--connection node_2 +SET SESSION wsrep_sync_wait = 0; +SELECT COUNT(*) = 0 FROM t1; +--send INSERT INTO t1 VALUES (1); + +--connection node_1 +COMMIT; + +--connection node_2a +SET GLOBAL debug = ''; +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; + +--connection node_2 +--error ER_DUP_ENTRY,ER_LOCK_DEADLOCK +--reap +ROLLBACK; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#8.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#8.test new file mode 100644 index 00000000000..55210386044 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#8.test @@ -0,0 +1,63 @@ +--source include/big_test.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# InnoDB FULLTEXT indexes +# + +SET SESSION wsrep_trx_fragment_size = 1; +CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); + +# +# Fulltext index creation causes the creation of multiple system tables +# + +--connection node_1 +CREATE TABLE t1 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(100), FULLTEXT (f2)) ENGINE=InnoDB; + +--connection node_2 +SELECT COUNT(*) = 13 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE name LIKE 'test/%'; + +# +# Fulltext insertion causes a flurry of updates on those system tables +# + +--connection node_1 +# Insert 10K rows +INSERT INTO t1 (f2) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; + +--connection node_2 +SELECT COUNT(f2) = 10000 FROM t1 WHERE MATCH(f2) AGAINST ('foobarbaz'); + +UPDATE t1 SET f2 = 'abcdefjhk'; + +--connection node_1 +SELECT COUNT(f2) = 10000 FROM t1 WHERE MATCH(f2) AGAINST ('abcdefjhk'); + +--connection node_2 + +DROP TABLE t1; + +# +# Same on a table with no PK +# + +--connection node_1 +CREATE TABLE t1 (f1 VARCHAR(100), FULLTEXT (f1)) ENGINE=InnoDB; + +--connection node_2 +# We insert only 1K rows here, because updates without a PK are very slow +INSERT INTO t1 (f1) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3; + +--connection node_1 +SELECT COUNT(f1) = 1000 FROM t1 WHERE MATCH(f1) AGAINST ('foobarbaz'); + +UPDATE t1 SET f1 = 'abcdefjhk'; + +--connection node_2 +SELECT COUNT(f1) = 1000 FROM t1 WHERE MATCH(f1) AGAINST ('abcdefjhk'); + +DROP TABLE t1; +DROP TABLE ten; diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#9.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#9.test new file mode 100644 index 00000000000..cbecf40fadf --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#9.test @@ -0,0 +1,44 @@ +# +# mysql-wsrep-features#9 Hang in galera::ReplicatorSMM::cert with Streaming Replication +# when running the galera_kill_ddl.test test +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/big_test.inc + +--connection node_1 + +# Enable the master to continue running during the split-brain situation that +# occurs when the slave is killed +--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options` +SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; + +SET SESSION wsrep_trx_fragment_size = 1; + +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; + +--connection node_2 +--source include/kill_galera.inc + +--connection node_1 +ALTER TABLE t1 ADD COLUMN f2 INTEGER; + +--connection node_2 +--source include/start_mysqld.inc +--source include/galera_wait_ready.inc + +--let $galera_connection_name = node_2a +--let $galera_server_number = 2 +--source include/galera_connect.inc +--connection node_2a + +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='t1'; +SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + +--connection node_1 +--disable_query_log +--eval SET GLOBAL wsrep_provider_options = '$wsrep_provider_options_orig'; +--enable_query_log + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#93.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#93.test new file mode 100644 index 00000000000..ba82473ae79 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#93.test @@ -0,0 +1,29 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# This test sets a SAVEPOINT at the very beginning +# of the transaction. When ROLLBACK TO SAVEPOINT is +# issued, mysql performs a full rollback on SEs that +# where not part of the transaction. +# Test that SR transactions are rolled back, and +# cleaned up properly in this case. +# + +CREATE TABLE t1 (f1 INTEGER); +SET SESSION WSREP_TRX_FRAGMENT_SIZE=1; + +START TRANSACTION; + +SAVEPOINT a; +INSERT INTO t1 VALUES (1); +ROLLBACK TO SAVEPOINT a; + +INSERT INTO t1 values (2); +COMMIT; + +SELECT COUNT(*) = 0 from wsrep_schema.SR; +--connection node_2 +SELECT COUNT(*) = 0 from wsrep_schema.SR; + +DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-features#96.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#96.test new file mode 100644 index 00000000000..c773b310183 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#96.test @@ -0,0 +1,45 @@ +# mysql-wsrep-features#96 - "Sanity check failed" with SR and statement rolled back due to error + +--source include/galera_cluster.inc +--source include/have_innodb.inc + + +--connection node_1 + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY); +CREATE TABLE t2 (f2 VARCHAR(32)); + +SET SESSION wsrep_trx_fragment_size=1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1); + +# This statement causes full transaction rollback +# rather than just statement rollback, as it is run under SR + +--error ER_LOCK_DEADLOCK +INSERT INTO t1 VALUES (2),(1); +INSERT INTO t2 VALUES ('abc'); + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; + +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 1 FROM t2; + +--connection node_1 +ROLLBACK; + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; + +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM t2; + +--connection node_1 +DROP TABLE t1; +DROP TABLE t2; + + + + diff --git a/mysql-test/suite/innodb/r/innodb-index-online-fk.result b/mysql-test/suite/innodb/r/innodb-index-online-fk.result index 47fc8e8b840..6ec5a72db25 100644 --- a/mysql-test/suite/innodb/r/innodb-index-online-fk.result +++ b/mysql-test/suite/innodb/r/innodb-index-online-fk.result @@ -118,7 +118,7 @@ SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, informati name name test/child a1 test/child a2 -SELECT NAME FROM information_schema.INNODB_SYS_TABLES; +SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%'; NAME SYS_DATAFILES SYS_FOREIGN @@ -310,7 +310,7 @@ SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, informati name name test/child a1 test/child a2 -SELECT NAME FROM information_schema.INNODB_SYS_TABLES; +SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%'; NAME SYS_DATAFILES SYS_FOREIGN @@ -336,7 +336,7 @@ SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, informati name name test/child a2 test/child a3 -SELECT NAME FROM information_schema.INNODB_SYS_TABLES; +SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%'; NAME SYS_DATAFILES SYS_FOREIGN @@ -373,7 +373,7 @@ SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, informati name name test/child a1 test/child a2 -SELECT NAME FROM information_schema.INNODB_SYS_TABLES; +SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%'; NAME SYS_DATAFILES SYS_FOREIGN @@ -410,7 +410,7 @@ SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, informati name name test/child a2 test/child a3 -SELECT NAME FROM information_schema.INNODB_SYS_TABLES; +SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%'; NAME SYS_DATAFILES SYS_FOREIGN diff --git a/mysql-test/suite/innodb/t/galera.skip b/mysql-test/suite/innodb/t/galera.skip new file mode 100644 index 00000000000..1991ce10cc4 --- /dev/null +++ b/mysql-test/suite/innodb/t/galera.skip @@ -0,0 +1,53 @@ +innodb : deadlock, failure in UPDATE IGNORE, lp1372296 +innodb_ctype_ldml : Test contains statements unsafe to replicate in statement-based replication +innodb-autoinc : deadlock, failure in REPLACE, lp1372296 +innodb_mysql : deadlock due to DDL +innodb_buffer_pool_load : Test contains statements unsafe to replicate in statement-based replication +innodb-autoinc-56228 : deadlock, lp1372301 +innodb_lock_wait_timeout_1 : Test contains statements unsafe to replicate in statement-based replication +innodb-consistent : Test contains statements unsafe to replicate in statement-based replication +innodb-semi-consistent : Test contains statements unsafe to replicate in statement-based replication +innodb-index : DDL concurrent with transaction +innodb-lock : deadlock on INSERT IGNORE, lp1372296 +innodb-status-output : Test performs server restart +innodb-wl5522 : Test contains statements unsafe to replicate in statement-based replication +innodb-wl6445 : Test performs server restart +innodb_bug40360 : Test contains statements unsafe to replicate in statement-based replication +innodb_bug40565 : Galera git bug #137 - Invalid deadlock on UPDATE to NULL without a PK +innodb_bug42419 : Test contains statements unsafe to replicate in statement-based replication +innodb_bug49164 : Test contains statements unsafe to replicate in statement-based replication +innodb_bug45357 : impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging +innodb_bug52663 : Test contains statements unsafe to replicate in statement-based replication +innodb_bug59733 : Test contains statements unsafe to replicate in statement-based replication +innodb_gis : Test contains statements unsafe to replicate in statement-based replication +innodb_prefix_index_restart_server : crash, lp1372288 +innodb_stats_external_pages : Test contains statements unsafe to replicate in statement-based replication +innodb-2byte-collation : Unsafe statement written to the binary log +innodb-change-buffer-recovery : Test contains statements unsafe to replicate in statement-based replication +innodb_bug53756 : Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT +innodb-alter-autoinc : AUTO_INCREMENT differences +innodb_bug13635833 : Test contains statements unsafe to replicate in statement-based replication +innodb_bug13867871 : mysql-wsrep#3 - innodb_bug13867871 test fails with wsrep loaded +innodb_bug14006907 : DDL lock wait timeout +innodb_bug38231 : Deadlock on UNLOCK TABLE +innodb_bug-13628249 : mysql-wsrep#12 InnoDB: Failing assertion: !srv_read_only_mode with server restart +innodb-wl6445-1 : mysql-wsrep#12 InnoDB: Failing assertion: !srv_read_only_mode with server restart +innodb-wl6445-2 : mysql-wsrep#12 InnoDB: Failing assertion: !srv_read_only_mode with server restart +innodb_bug12400341 : Test does not account for applier threads when performing SHOW PROCESSLIST +innodb-blob : 'Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging' +innodb_corrupt_bit : 'Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.' +innodb-index-online : ALTER succeeds as it is given a higher priority +innodb-table-online : ALTER succeeds as it is given a higher priority +innodb-index-online-purge : ALTER succeeds as it is given a higher priority +innodb-wl5522-debug : Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. +innodb_stats_table_flag_auto_recalc : Performs multiple restarts in a row which causes '1047: Unknown command' errors +innodb-lock-inherit-read_commited : Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT +innodb-index-debug : Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT +flush-hang : Unsafe statement written to the binary log +innodb_deadlock_with_autoinc : Test uses autoinc_lock_mode = 0 +innodb_stats_del_mark : Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. +ibuf_not_empty : InnoDB: Failing assertion: !srv_read_only_mode with server restart +innodb_force_recovery : InnoDB: Failing assertion: !srv_read_only_mode with server restart +innodb-system-table-view : Result depends on whether galera is loaded or not +innodb-wl5980-linux : Fails because portability_wl5980_linux.zip does not contain wsrep_schema +innodb-multiple-tablespaces : No changes to SR table are allowed if innodb-force-recovery > 0
\ No newline at end of file diff --git a/mysql-test/suite/innodb/t/innodb-index-online-fk.test b/mysql-test/suite/innodb/t/innodb-index-online-fk.test index 5c8954064ce..dd185a9843a 100644 --- a/mysql-test/suite/innodb/t/innodb-index-online-fk.test +++ b/mysql-test/suite/innodb/t/innodb-index-online-fk.test @@ -105,7 +105,7 @@ SELECT * FROM information_schema.INNODB_SYS_FOREIGN_COLS; SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, information_schema.innodb_sys_tables t2 WHERE t1.table_id = t2.table_id AND t2.name LIKE "%child" ORDER BY t1.name; -SELECT NAME FROM information_schema.INNODB_SYS_TABLES; +SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%'; # this should succeed, since we disabled the foreign key check INSERT INTO child VALUES(5,4); @@ -287,7 +287,7 @@ SET DEBUG_DBUG = @saved_debug_dbug; SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN; SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS; SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, information_schema.innodb_sys_tables t2 WHERE t1.table_id = t2.table_id AND t2.name LIKE "%child" ORDER BY t1.name; -SELECT NAME FROM information_schema.INNODB_SYS_TABLES; +SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%'; # This should be successful. It will also check any left over # from previous failed operation (if dictionary entries not cleaned, @@ -300,7 +300,7 @@ ALGORITHM = INPLACE; SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN; SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS; SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, information_schema.innodb_sys_tables t2 WHERE t1.table_id = t2.table_id AND t2.name LIKE "%child" ORDER BY t1.name; -SELECT NAME FROM information_schema.INNODB_SYS_TABLES; +SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%'; SHOW CREATE TABLE child; @@ -317,7 +317,7 @@ ALGORITHM = INPLACE; SELECT * from information_schema.INNODB_SYS_FOREIGN; SELECT * from information_schema.INNODB_SYS_FOREIGN_COLS; SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, information_schema.innodb_sys_tables t2 WHERE t1.table_id = t2.table_id AND t2.name LIKE "%child" ORDER BY t1.name; -SELECT NAME FROM information_schema.INNODB_SYS_TABLES; +SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%'; SHOW CREATE TABLE child; @@ -333,7 +333,7 @@ ALGORITHM = INPLACE; SELECT * from information_schema.INNODB_SYS_FOREIGN; SELECT * from information_schema.INNODB_SYS_FOREIGN_COLS; SELECT t2.name, t1.name FROM information_schema.innodb_sys_columns t1, information_schema.innodb_sys_tables t2 WHERE t1.table_id = t2.table_id AND t2.name LIKE "%child" ORDER BY t1.name; -SELECT NAME FROM information_schema.INNODB_SYS_TABLES; +SELECT NAME FROM information_schema.INNODB_SYS_TABLES WHERE NAME NOT LIKE 'wsrep%'; SHOW CREATE TABLE child; diff --git a/packaging/deb-in/CMakeLists.txt b/packaging/deb-in/CMakeLists.txt new file mode 100644 index 00000000000..aa14eb42425 --- /dev/null +++ b/packaging/deb-in/CMakeLists.txt @@ -0,0 +1,357 @@ +# Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +IF(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") + RETURN() +ENDIF() +IF (NOT DEFINED DEB_CODENAME) + execute_process( + COMMAND lsb_release -cs + OUTPUT_VARIABLE DEB_CODENAME + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + SET (DEB_CODENAME ${DEB_CODENAME} CACHE STRING "") +ENDIF() +IF (DEFINED WITH_NDBCLUSTER_STORAGE_ENGINE) + SET (DEB_BASE_PRODUCT "cluster-") + SET (DEB_BASE_PRODUCTC "Cluster ") + SET (DEB_BASE_VERSION ${NDBVERSION}) + SET (DEB_CONTROL_SERVER_CONFLICT_NDB "mysql-community-server, mysql-commercial-server") + SET (DEB_CONTROL_CLIENT_CONFLICT_NDB "mysql-community-client, mysql-commercial-client") +ELSE() + SET (DEB_BASE_PRODUCT "") + SET (DEB_BASE_PRODUCTC "") + SET (DEB_BASE_VERSION ${VERSION}) + SET (DEB_CONTROL_SERVER_CONFLICT_NDB "mysql-cluster-community-server, mysql-cluster-commercial-server") + SET (DEB_CONTROL_CLIENT_CONFLICT_NDB "mysql-cluster-community-client, mysql-cluster-commercial-client") +ENDIF() + +SET (DEB_BASE_VERSION "${DEB_BASE_VERSION}-${WSREP_VERSION}") + +# Commercial or community +IF (DEB_PRODUCT STREQUAL "commercial") + message (FATAL_ERROR "mysql-wsrep is GPL only, no commercial builds") + SET (DEB_COPYRIGHT_UPSTREAMNAME "MySQL Commercial Server ${MYSQL_BASE_VERSION}") + SET (DEB_PRODUCTNAME "${DEB_BASE_PRODUCT}commercial") + SET (DEB_PRODUCTNAMEC "${DEB_BASE_PRODUCTC}Commercial") + SET (DEB_NOTPRODUCTNAME "${DEB_BASE_PRODUCT}community") + SET (DEB_LICENSENAME "Advanced") + SET (DEB_INSTALL_LICENSEFILE "LICENSE.mysql") + SET (DEB_SERVERVERSION "${DEB_BASE_VERSION}+commercial.1") + SET (DEB_PLUGIN_SETPERMISSION "") + SET (DEB_MAN_SETPERMISSION "") + # List of plugins that are only in commercial packages + # Plugins that are in both community and commercial should NOT be added here + SET (DEB_INCLUDE_BINARIES_EXTRA +" +debian/extra/audit_log-plugin +debian/extra/authentication_pam-plugin +debian/extra/firewall-plugin +debian/extra/openssl_udf-plugin +debian/extra/thread_pool-plugin +") + SET (DEB_INSTALL_SERVER_PLUGINS +" +usr/lib/mysql/plugin/audit_log.so +usr/lib/mysql/plugin/authentication_pam.so +usr/lib/mysql/plugin/openssl_udf.so +usr/lib/mysql/plugin/thread_pool.so +usr/lib/mysql/plugin/firewall.so +usr/lib/mysql/plugin/debug/audit_log.so +usr/lib/mysql/plugin/debug/authentication_pam.so +usr/lib/mysql/plugin/debug/keyring_okv.so +usr/lib/mysql/plugin/debug/openssl_udf.so +usr/lib/mysql/plugin/debug/thread_pool.so +usr/lib/mysql/plugin/debug/firewall.so +") + SET (DEB_REMOVEPATTERN "gpl.in") +ELSE() + SET (DEB_PRODUCT "${DEB_BASE_PRODUCT}community") + SET (DEB_COPYRIGHT_UPSTREAMNAME "MySQL Server ${MYSQL_BASE_VERSION}") + SET (DEB_PRODUCTNAME "${DEB_BASE_PRODUCT}community") + SET (DEB_PRODUCTNAMEC "${DEB_BASE_PRODUCTC}Community") + SET (DEB_NOTPRODUCTNAME "${DEB_BASE_PRODUCT}commercial") + SET (DEB_LICENSENAME "GPL") + SET (DEB_INSTALL_LICENSEFILE "COPYING") + SET (DEB_SERVERVERSION "${DEB_BASE_VERSION}+1") + SET (DEB_REMOVEPATTERN "com.in") + SET (DEB_PLUGIN_SETPERMISSION "usr/bin/mysql_setpermission") + SET (DEB_MAN_SETPERMISSION "usr/share/man/man1/mysql_setpermission.1") +ENDIF() + +# mysql-wsrep ! +SET (DEB_PRODUCTNAME "wsrep") +SET (DEB_PRODUCTNAMEC "Wsrep") +SET (DEB_PRODUCTSERIES "-5.6") +SET (DEB_WSREP_README "README-wsrep") + + +SET (FILES_STARTUP_SYSV +" +etc/init.d/mysql +usr/bin/mysqld_safe +") +SET (FILES_STARTUP_UPSTART +" +Not Yet Implememted: Upstart File List +") + +# Platform specifics. The differences are generally only distro version +# and whether or not Systemd and/or apparmor are available +IF (DEB_CODENAME STREQUAL "wheezy") + SET (DEB_PLATFORMRELEASE "debian7") + # Following the Oracle example, we package for Debian 7 + # using only SysV init and no Apparmor. + SET (DEB_CONTROL_BDEPS "") + SET (DEB_INSTALL_SOURCE_XZ "") + SET (DEB_RULES_INSTALL_SYSTEMD "") + SET (DEB_RULES_INSTALL_APPARMOR "") + SET (DEB_RULES_APPARMOR_LOAD "") + SET (DEB_RULES_SYSTEMD_ENABLE "") + SET (DEB_RULES_SYSTEMD_START "") + SET (DEB_INSTALL_SERVER_SYSTEMD "") + SET (DEB_INSTALL_SERVER_APPARMOR "") + SET (DEB_SERVICE_SERVER_EXECPRE "") + SET (DEB_SERVICE_SERVER_EXECPOST "") + SET (DEB_INIT_APPARMOR "") + SET (DEB_STARTUP "SYSV") +ELSEIF(DEB_CODENAME STREQUAL "jessie") + SET (DEB_PLATFORMRELEASE "debian8") + # Improving on Oracle, we would prefer to package for Debian 8 + # using both SysV init and Systemd, but still no Apparmor. + SET (DEB_CONTROL_BDEPS "") + SET (DEB_INSTALL_SOURCE_XZ "../*.tar.xz usr/src/mysql/") + SET (DEB_RULES_INSTALL_SYSTEMD "") + SET (DEB_RULES_INSTALL_APPARMOR "") + SET (DEB_RULES_APPARMOR_LOAD "") + SET (DEB_SYSTEMD_SERVICE_NAME "") + SET (DEB_RULES_SYSTEMD_ENABLE "") + SET (DEB_RULES_SYSTEMD_START "") + SET (DEB_INSTALL_SERVER_SYSTEMD "") + SET (DEB_INSTALL_SERVER_APPARMOR "") + SET (DEB_SERVICE_SERVER_EXECPRE "") + SET (DEB_SERVICE_SERVER_EXECPOST "") + SET (DEB_INIT_APPARMOR "") + # Debian 8 comes with both SysV init and Systemd, + # but "scripts/CMakeLists.txt" enforces an either-or. + SET (DEB_STARTUP "SYSV") + # For now, we go with Systemd only. +ELSEIF(DEB_CODENAME STREQUAL "stretch") + SET (DEB_PLATFORMRELEASE "debian9") + SET (DEB_CONTROL_BDEPS "") + SET (DEB_INSTALL_SOURCE_XZ "../*.tar.xz usr/src/mysql/") + SET (DEB_RULES_INSTALL_SYSTEMD "") + SET (DEB_RULES_INSTALL_APPARMOR "") + SET (DEB_RULES_APPARMOR_LOAD "") + SET (DEB_RULES_SYSTEMD_ENABLE "") + SET (DEB_RULES_SYSTEMD_START "") + SET (DEB_INSTALL_SERVER_SYSTEMD "") + SET (DEB_INSTALL_SERVER_APPARMOR "") + SET (DEB_SERVICE_SERVER_EXECPRE "") + SET (DEB_INIT_APPARMOR "") + SET (DEB_STARTUP "SYSV") +ELSEIF(DEB_CODENAME STREQUAL "precise") + SET (DEB_PLATFORMRELEASE "ubuntu12.04") + SET (DEB_CONTROL_BDEPS "dh-apparmor") + SET (DEB_INSTALL_SOURCE_XZ "") + SET (DEB_RULES_INSTALL_SYSTEMD "") + SET (DEB_RULES_INSTALL_APPARMOR + "install -g root -o root -m 0644 -D debian/extra/apparmor-profile debian/tmp/etc/apparmor.d/usr.sbin.mysqld") + SET (DEB_RULES_APPARMOR_LOAD + "dh_apparmor -pmysql-${DEB_PRODUCTNAME}-server --profile-name=usr.sbin.mysqld") + SET (DEB_RULES_SYSTEMD_ENABLE "") + SET (DEB_RULES_SYSTEMD_START "") + SET (DEB_INSTALL_SERVER_SYSTEMD "") + SET (DEB_INSTALL_SERVER_APPARMOR "etc/apparmor.d/usr.sbin.mysqld") + SET (DEB_SERVICE_SERVER_EXECPRE "") + SET (DEB_SERVICE_SERVER_EXECPOST "") + SET (DEB_INIT_APPARMOR "/lib/init/apparmor-profile-load usr.sbin.mysqld") + SET (DEB_STARTUP "SYSV") +ELSEIF(DEB_CODENAME STREQUAL "trusty") + SET (DEB_PLATFORMRELEASE "ubuntu14.04") + SET (DEB_CONTROL_BDEPS "dh-apparmor") + SET (DEB_INSTALL_SOURCE_XZ "") + SET (DEB_RULES_INSTALL_SYSTEMD "") + SET (DEB_RULES_INSTALL_APPARMOR + "install -g root -o root -m 0644 -D debian/extra/apparmor-profile debian/tmp/etc/apparmor.d/usr.sbin.mysqld") + SET (DEB_RULES_APPARMOR_LOAD + "dh_apparmor -pmysql-${DEB_PRODUCTNAME}-server --profile-name=usr.sbin.mysqld") + SET (DEB_RULES_SYSTEMD_ENABLE "") + SET (DEB_RULES_SYSTEMD_START "") + SET (DEB_INSTALL_SERVER_SYSTEMD "") + SET (DEB_INSTALL_SERVER_APPARMOR "etc/apparmor.d/usr.sbin.mysqld") + SET (DEB_SERVICE_SERVER_EXECPRE "") + SET (DEB_SERVICE_SERVER_EXECPOST "") + SET (DEB_INIT_APPARMOR "/lib/init/apparmor-profile-load usr.sbin.mysqld") + SET (DEB_STARTUP "SYSV") +ELSEIF(DEB_CODENAME STREQUAL "wily") + SET (DEB_PLATFORMRELEASE "ubuntu15.10") + SET (DEB_CONTROL_BDEPS "dh-apparmor, dh-systemd (>=1.5)") + SET (DEB_INSTALL_SOURCE_XZ "../*.tar.xz usr/src/mysql/") + SET (DEB_RULES_INSTALL_SYSTEMD + "install -m 0755 debian/extra/mysql-systemd-start debian/tmp/usr/share/mysql/") + SET (DEB_RULES_INSTALL_APPARMOR + "install -g root -o root -m 0644 -D debian/extra/apparmor-profile debian/tmp/etc/apparmor.d/usr.sbin.mysqld") + SET (DEB_RULES_APPARMOR_LOAD + "dh_apparmor -pmysql-community-server --profile-name=usr.sbin.mysqld") + SET (DEB_SYSTEMD_SERVICE_NAME "mysql") + SET (DEB_RULES_SYSTEMD_ENABLE "dh_systemd_enable --no-enable --name=mysql") + SET (DEB_RULES_SYSTEMD_START "dh_systemd_start --restart-after-upgrade") + SET (DEB_INSTALL_SERVER_SYSTEMD "usr/share/mysql/mysql-systemd-start") + SET (DEB_INSTALL_SERVER_APPARMOR "etc/apparmor.d/usr.sbin.mysqld") + SET (DEB_SERVICE_SERVER_EXECPRE + "ExecStartPre=/usr/share/mysql/mysql-systemd-start pre") + SET (DEB_SERVICE_SERVER_EXECPOST + "ExecStartPost=/usr/share/mysql/mysql-systemd-start post") + SET (DEB_INIT_APPARMOR "/lib/init/apparmor-profile-load usr.sbin.mysqld") + SET (DEB_STARTUP "SYSTEMD") +ELSEIF(DEB_CODENAME STREQUAL "xenial") + SET (DEB_PLATFORMRELEASE "ubuntu16.04") + SET (DEB_CONTROL_BDEPS "dh-apparmor") + SET (DEB_INSTALL_SOURCE_XZ "../*.tar.xz usr/src/mysql/") + SET (DEB_RULES_INSTALL_SYSTEMD "") + SET (DEB_RULES_INSTALL_APPARMOR + "install -g root -o root -m 0644 -D debian/extra/apparmor-profile debian/tmp/etc/apparmor.d/usr.sbin.mysqld") + SET (DEB_RULES_APPARMOR_LOAD + "dh_apparmor -pmysql-${DEB_PRODUCTNAME}-server --profile-name=usr.sbin.mysqld") + SET (DEB_SYSTEMD_SERVICE_NAME "") + SET (DEB_RULES_SYSTEMD_ENABLE "") + SET (DEB_RULES_SYSTEMD_START "") + SET (DEB_INSTALL_SERVER_SYSTEMD "") + SET (DEB_INSTALL_SERVER_APPARMOR "etc/apparmor.d/usr.sbin.mysqld") + SET (DEB_SERVICE_SERVER_EXECPRE "") + SET (DEB_SERVICE_SERVER_EXECPOST "") + SET (DEB_INIT_APPARMOR "/lib/apparmor/profile-load usr.sbin.mysqld") + SET (DEB_STARTUP "SYSV") +ELSEIF(DEB_CODENAME STREQUAL "yakkety") + SET (DEB_PLATFORMRELEASE "ubuntu16.10") + SET (DEB_CONTROL_BDEPS "dh-apparmor, dh-systemd (>=1.5)") + SET (DEB_INSTALL_SOURCE_XZ "../*.tar.xz usr/src/mysql/") + SET (DEB_RULES_INSTALL_SYSTEMD + "install -m 0755 debian/extra/mysql-systemd-start debian/tmp/usr/share/mysql/") + SET (DEB_RULES_INSTALL_APPARMOR + "install -g root -o root -m 0644 -D debian/extra/apparmor-profile debian/tmp/etc/apparmor.d/usr.sbin.mysqld") + SET (DEB_RULES_APPARMOR_LOAD + "dh_apparmor -pmysql-${DEB_PRODUCTNAME}-server --profile-name=usr.sbin.mysqld") + SET (DEB_SYSTEMD_SERVICE_NAME "mysql") + SET (DEB_RULES_SYSTEMD_ENABLE "dh_systemd_enable --no-enable --name=mysql") + SET (DEB_RULES_SYSTEMD_START "dh_systemd_start --restart-after-upgrade") + SET (DEB_INSTALL_SERVER_SYSTEMD "usr/share/mysql/mysql-systemd-start") + SET (DEB_INSTALL_SERVER_APPARMOR "etc/apparmor.d/usr.sbin.mysqld") + SET (DEB_SERVICE_SERVER_EXECPRE + "ExecStartPre=/usr/share/mysql/mysql-systemd-start pre") + SET (DEB_SERVICE_SERVER_EXECPOST + "ExecStartPost=/usr/share/mysql/mysql-systemd-start post") + SET (DEB_INIT_APPARMOR "/lib/apparmor/profile-load usr.sbin.mysqld") + SET (DEB_STARTUP "SYSTEMD") +ELSEIF(DEB_CODENAME STREQUAL "zesty") + SET (DEB_PLATFORMRELEASE "ubuntu17.04") + SET (DEB_CONTROL_BDEPS "dh-apparmor, dh-systemd (>=1.5)") + SET (DEB_INSTALL_SOURCE_XZ "../*.tar.xz usr/src/mysql/") + SET (DEB_RULES_INSTALL_SYSTEMD + "install -m 0755 debian/extra/mysql-systemd-start debian/tmp/usr/share/mysql/") + SET (DEB_RULES_INSTALL_APPARMOR + "install -g root -o root -m 0644 -D debian/extra/apparmor-profile debian/tmp/etc/apparmor.d/usr.sbin.mysqld") + SET (DEB_RULES_APPARMOR_LOAD + "dh_apparmor -pmysql-${DEB_PRODUCTNAME}-server --profile-name=usr.sbin.mysqld") + SET (DEB_RULES_SYSTEMD_ENABLE "dh_systemd_enable --name=mysql") + SET (DEB_RULES_SYSTEMD_START "dh_systemd_start --restart-after-upgrade") + SET (DEB_INSTALL_SERVER_SYSTEMD "usr/share/mysql/mysql-systemd-start") + SET (DEB_INSTALL_SERVER_APPARMOR "etc/apparmor.d/usr.sbin.mysqld") + SET (DEB_SERVICE_SERVER_EXECPRE + "ExecStartPre=/usr/share/mysql/mysql-systemd-start pre") + SET (DEB_INIT_APPARMOR "/lib/apparmor/profile-load usr.sbin.mysqld") +ELSE() + MESSAGE(STATUS + "Skipping deb packaging on unsupported platform ${DEB_CODENAME}.") + RETURN() +ENDIF() + +# All files are configured and copied to the debian/ directory, which is used +# by debuild to make the packages +# 5.7.11 builds out-of-source. Hack: have duplicate debian/ +SET (DEB_ROOT ${CMAKE_SOURCE_DIR}/packaging/deb-in) +FILE(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/debian) +FILE(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/debian) +FILE(GLOB_RECURSE SOURCEFILES RELATIVE "${DEB_ROOT}" "${DEB_ROOT}/*") +# Skip the copyright file from the "other" product type +LIST(REMOVE_ITEM SOURCEFILES "copyright.${DEB_REMOVEPATTERN}") +LIST(REMOVE_ITEM SOURCEFILES "CMakeLists.txt") +# Combine the list of all startup files to be included, +# skip Debian magical init files unless needed +IF(DEB_PRODUCTNAME STREQUAL "wsrep") + SET(COMMON_WSREP_CONFLICTS "mysql-common (>= 5.7)") + LIST(REMOVE_ITEM SOURCEFILES "mysql-common.install.in") + LIST(REMOVE_ITEM SOURCEFILES "mysql-common.dirs.in") + LIST(REMOVE_ITEM SOURCEFILES "mysql-common.postinst.in") + LIST(REMOVE_ITEM SOURCEFILES "mysql-common.postrm.in") +ENDIF() +IF(DEB_STARTUP MATCHES ".*SYSV.*") + SET (DEB_FILES_STARTUP ${FILES_STARTUP_SYSV}) +ELSE() + LIST(REMOVE_ITEM SOURCEFILES + "mysql-packagesource-server-SERIES.mysql.init.in") +ENDIF() +IF(DEB_STARTUP MATCHES ".*SYSTEMD.*") + SET (DEB_FILES_STARTUP + ${DEB_FILES_STARTUP} + ${FILES_STARTUP_SYSTEMD}) +ELSE() + LIST(REMOVE_ITEM SOURCEFILES + "mysql-packagesource-server-SERIES.mysql.service.in") +ENDIF() +# Don't install systemd file on systems without systemd +IF(DEB_INSTALL_SERVER_SYSTEMD STREQUAL "") + LIST(REMOVE_ITEM SOURCEFILES "mysql-packagesource-server.mysql.service.in") +ENDIF() + +FOREACH (SOURCEFILE ${SOURCEFILES}) + STRING(REGEX REPLACE "-packagesource-" "-${DEB_PRODUCTNAME}-" + TMPFILE ${SOURCEFILE}) + STRING(REGEX REPLACE "-SERIES" "${DEB_PRODUCTSERIES}" TMPFILE ${TMPFILE}) + # Strip away the input file endings from the destination filenames + STRING(REGEX REPLACE ".in$" "" TMPFILE ${TMPFILE}) + STRING(REGEX REPLACE ".gpl$" "" TMPFILE ${TMPFILE}) + STRING(REGEX REPLACE ".com$" "" DESTFILE ${TMPFILE}) + CONFIGURE_FILE("${DEB_ROOT}/${SOURCEFILE}" + "${CMAKE_BINARY_DIR}/debian/${DESTFILE}" @ONLY) + CONFIGURE_FILE("${DEB_ROOT}/${SOURCEFILE}" + "${CMAKE_SOURCE_DIR}/debian/${DESTFILE}" @ONLY) +ENDFOREACH() +EXECUTE_PROCESS( + COMMAND chmod +x ${CMAKE_BINARY_DIR}/debian/rules +) +IF(DEB_PRODUCTNAME STREQUAL "wsrep") +FILE(APPEND "${CMAKE_BINARY_DIR}/debian/control" " +Package: mysql-common +Architecture: any +Pre-depends: debconf (>= 0.2.17), + \${misc:Pre-Depends} +Multi-Arch: foreign +Depends: \${misc:Depends}, + \${shlibs:Depends}, + mysql-wsrep-common +Description: MySQL Common + The MySQL(TM) software delivers a very fast, multi-threaded, multi-user, + and robust SQL (Structured Query Language) database server. MySQL Server + is intended for mission-critical, heavy-load production systems as well + as for embedding into mass-deployed software. MySQL is a trademark of + Oracle. This package contains common files needed by MySQL client + library and the MySQL database server. + This package is a dummy replacement for the case when using mysql WSREP + implementation to satisfy dependencies of other packages + like libmysqlclient18. It depends on any mysql-wsrep-common +") +ENDIF() diff --git a/plugin/wsrep_info/plugin.cc b/plugin/wsrep_info/plugin.cc index 428bcc5dcfc..ab871e81ed6 100644 --- a/plugin/wsrep_info/plugin.cc +++ b/plugin/wsrep_info/plugin.cc @@ -202,9 +202,11 @@ static int wsrep_status_fill_table(THD *thd, TABLE_LIST *tables, COND *cond) ->store(view.state_id.seqno, 0); table->field[COLUMN_WSREP_STATUS_CLUSTER_CONF_ID]->store(view.view, 0); +#ifdef OLD_MARIADB const char *gap= (view.state_gap == true) ? "YES" : "NO"; table->field[COLUMN_WSREP_STATUS_GAP]->store(gap, strlen(gap), system_charset_info); +#endif table->field[COLUMN_WSREP_STATUS_PROTO_VERSION]->store(view.proto_ver, 0); if (schema_table_store_record(thd, table)) diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 5797bdc68d7..5f09ac3c235 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -265,7 +265,16 @@ wsrep_recover_position() { wsrep_start_position_opt="--wsrep_start_position=$start_pos" fi - [ $ret -eq 0 ] && rm $wr_logfile + if [ $ret -eq 0 ] ; then + local wr_logfile_permanent="$DATADIR/wsrep_recovery.ok" + else + local wr_logfile_permanent="$DATADIR/wsrep_recovery.fail" + fi + touch $wr_logfile_permanent + [ "$euid" = "0" ] && chown $user $wr_logfile_permanent + chmod 600 $wr_logfile_permanent + cat "$wr_logfile" >> $wr_logfile_permanent + rm -f "$wr_logfile" return $ret } diff --git a/scripts/wsrep_sst_mysqldump.sh b/scripts/wsrep_sst_mysqldump.sh index faa3f10639b..10663216ca5 100644 --- a/scripts/wsrep_sst_mysqldump.sh +++ b/scripts/wsrep_sst_mysqldump.sh @@ -25,6 +25,7 @@ EINVAL=22 local_ip() { [ "$1" = "127.0.0.1" ] && return 0 + [ "$1" = "127.0.0.2" ] && return 0 [ "$1" = "localhost" ] && return 0 [ "$1" = "[::1]" ] && return 0 [ "$1" = "$(hostname -s)" ] && return 0 diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh index 79442d415e9..7f19131d0fe 100644 --- a/scripts/wsrep_sst_xtrabackup-v2.sh +++ b/scripts/wsrep_sst_xtrabackup-v2.sh @@ -647,7 +647,7 @@ wait_for_listen() local HOST=$1 local PORT=$2 local MODULE=$3 - local LSOF_OUT + #local LSOF_OUT for i in {1..300} do diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 0037ff23153..8d5f0c1ce2d 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -18,17 +18,23 @@ IF(WITH_WSREP AND NOT EMBEDDED_LIBRARY) SET(WSREP_INCLUDES ${CMAKE_SOURCE_DIR}/wsrep) SET(WSREP_SOURCES + wsrep_utils.cc + wsrep_xid.cc wsrep_check_opts.cc - wsrep_hton.cc - wsrep_mysqld.cc + wsrep_mysqld.cc wsrep_notify.cc wsrep_sst.cc - wsrep_utils.cc wsrep_var.cc wsrep_binlog.cc wsrep_applier.cc wsrep_thd.cc - wsrep_xid.cc + wsrep_sr_file.cc + wsrep_sr_table.cc + wsrep_thd_pool.cc + wsrep_schema.cc + wsrep_sr.cc + wsrep_trans_observer.cc + wsrep_plugin.cc ) SET(WSREP_LIB wsrep) ELSE() @@ -42,7 +48,6 @@ ${PCRE_INCLUDES} ${ZLIB_INCLUDE_DIR} ${SSL_INCLUDE_DIRS} ${CMAKE_BINARY_DIR}/sql -${WSREP_INCLUDES} ) diff --git a/sql/events.cc b/sql/events.cc index af020d5240e..6b8aad4f1d1 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -341,7 +341,6 @@ Events::create_event(THD *thd, Event_parse_data *parse_data) if (lock_object_name(thd, MDL_key::EVENT, parse_data->dbname.str, parse_data->name.str)) DBUG_RETURN(TRUE); - if (check_db_dir_existence(parse_data->dbname.str)) { my_error(ER_BAD_DB_ERROR, MYF(0), parse_data->dbname.str); diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 262e791ec7a..61420e7ff25 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -405,6 +405,13 @@ const char *ha_partition::table_type() const // we can do this since we only support a single engine type return m_file[0]->table_type(); } +#ifdef WITH_WSREP +int ha_partition::wsrep_db_type() const +{ + // we can do this since we only support a single engine type + return ha_legacy_type(m_file[0]->ht); +} +#endif /* WITH_WSREP */ /* diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 8a251016703..79ef6355812 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -1505,5 +1505,8 @@ public: friend int cmp_key_rowid_part_id(void *ptr, uchar *ref1, uchar *ref2); friend int cmp_key_part_id(void *key_p, uchar *ref1, uchar *ref2); +#ifdef WITH_WSREP + virtual int wsrep_db_type() const; +#endif /* WITH_WSREP */ }; #endif /* HA_PARTITION_INCLUDED */ diff --git a/sql/handler.cc b/sql/handler.cc index b3481c7e429..cb3f156be81 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -55,6 +55,12 @@ #include "wsrep_mysqld.h" #include "wsrep.h" #include "wsrep_xid.h" +#ifdef WITH_WSREP +#include "wsrep_sr.h" +#endif +#include "wsrep_thd.h" +#include "wsrep_trans_observer.h" /* wsrep transaction hooks */ +#include "log.h" /* While we have legacy_db_type, we have this array to @@ -1168,8 +1174,8 @@ static int prepare_or_error(handlerton *ht, THD *thd, bool all) { /* avoid sending error, if we're going to replay the transaction */ #ifdef WITH_WSREP - if (ht != wsrep_hton || - err == EMSGSIZE || thd->wsrep_conflict_state != MUST_REPLAY) + if (ht->db_type != DB_TYPE_UNKNOWN || + err == EMSGSIZE || thd->wsrep_conflict_state() != MUST_REPLAY) #endif my_error(ER_ERROR_DURING_COMMIT, MYF(0), err); } @@ -1248,6 +1254,18 @@ ha_check_and_coalesce_trx_read_only(THD *thd, Ha_trx_info *ha_list, for (ha_info= ha_list; ha_info; ha_info= ha_info->next()) { +#ifdef WITH_WSREP + /* + Thd has wsrep_schema.SR open and may operate it + during prepare phase, set InnoDB ha_info read_write. + */ + if (WSREP_CLIENT(thd) && thd->wsrep_is_streaming() && + wsrep_SR_store && wsrep_SR_store_type == WSREP_SR_STORE_TABLE && + ha_info->ht()->db_type == DB_TYPE_INNODB) + { + ha_info->set_trx_read_write(); + } +#endif /* WITH_WSREP */ if (ha_info->is_trx_read_write()) ++rw_ha_count; @@ -1460,6 +1478,13 @@ int ha_commit_trans(THD *thd, bool all) need_prepare_ordered= FALSE; need_commit_ordered= FALSE; xid= thd->transaction.xid_state.xid.get_my_xid(); +#ifdef WITH_WSREP + if (WSREP(thd) && wsrep_before_prepare(thd, all)) + { + wsrep_override_error(thd, ER_ERROR_DURING_COMMIT); + goto wsrep_err; + } +#endif /* WITH_WSREP */ for (Ha_trx_info *hi= ha_info; hi; hi= hi->next()) { @@ -1483,6 +1508,13 @@ int ha_commit_trans(THD *thd, bool all) } DEBUG_SYNC(thd, "ha_commit_trans_after_prepare"); DBUG_EXECUTE_IF("crash_commit_after_prepare", DBUG_SUICIDE();); +#ifdef WITH_WSREP + if (WSREP(thd) && wsrep_after_prepare(thd, all)) + { + wsrep_override_error(thd, ER_ERROR_DURING_COMMIT); + goto err; + } +#endif /* WITH_WSREP */ #ifdef WITH_WSREP if (!error && WSREP_ON && wsrep_is_wsrep_xid(&thd->transaction.xid_state.xid)) @@ -1502,13 +1534,29 @@ int ha_commit_trans(THD *thd, bool all) cookie= tc_log->log_and_order(thd, xid, all, need_prepare_ordered, need_commit_ordered); if (!cookie) + { + WSREP_DEBUG("log_and_order has failed %lu %d", thd->thread_id, cookie); goto err; + } DEBUG_SYNC(thd, "ha_commit_trans_after_log_and_order"); DBUG_EXECUTE_IF("crash_commit_after_log", DBUG_SUICIDE();); error= commit_one_phase_2(thd, all, trans, is_real_trans) ? 2 : 0; - +#ifdef WITH_WSREP + if (error) + { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_exec_mode == LOCAL_COMMIT && + thd->wsrep_conflict_state() == MUST_ABORT) + { + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + (void)tc_log->unlog(cookie, xid); + goto wsrep_err; + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); +} +#endif /* WITH_WSREP */ DBUG_EXECUTE_IF("crash_commit_before_unlog", DBUG_SUICIDE();); if (tc_log->unlog(cookie, xid)) { @@ -1530,6 +1578,20 @@ done: goto end; /* Come here if error and we need to rollback. */ +#ifdef WITH_WSREP + wsrep_err: + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_exec_mode == LOCAL_COMMIT && + thd->wsrep_conflict_state() == MUST_ABORT) + { + WSREP_DEBUG("BF abort has happened after prepare & certify"); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + ha_rollback_trans(thd, TRUE); + } + else + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + +#endif /* WITH_WSREP */ err: error= 1; /* Transaction was rolled back */ /* @@ -1539,7 +1601,10 @@ err: */ if (!(thd->rgi_slave && thd->rgi_slave->is_parallel_exec)) ha_rollback_trans(thd, all); - + else + { + WSREP_DEBUG("WTF, rollback skipped %d %d",thd->rgi_slave, thd->rgi_slave->is_parallel_exec); + } end: if (rw_trans && mdl_request.ticket) { @@ -1673,7 +1738,6 @@ int ha_rollback_trans(THD *thd, bool all) */ DBUG_ASSERT(thd->transaction.stmt.ha_list == NULL || trans == &thd->transaction.stmt); - #ifdef HAVE_REPLICATION if (is_real_trans) { @@ -1708,6 +1772,9 @@ int ha_rollback_trans(THD *thd, bool all) DBUG_RETURN(1); } +#ifdef WITH_WSREP + (void) wsrep_before_rollback(thd, all); +#endif // WITH_WSREP if (ha_info) { /* Close all cursors that can not survive ROLLBACK */ @@ -1723,9 +1790,9 @@ int ha_rollback_trans(THD *thd, bool all) my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err); error=1; #ifdef WITH_WSREP - WSREP_WARN("handlerton rollback failed, thd %llu %lld conf %d SQL %s", - thd->thread_id, thd->query_id, thd->wsrep_conflict_state, - thd->query()); + WSREP_WARN("handlerton rollback failed, thd %lld %lld conf %d SQL %s", + thd->thread_id, thd->query_id, thd->wsrep_conflict_state(), + thd->query()); #endif /* WITH_WSREP */ } status_var_increment(thd->status_var.ha_rollback_count); @@ -1744,6 +1811,15 @@ int ha_rollback_trans(THD *thd, bool all) thd->transaction.xid_state.xa_state != XA_NOTR) thd->transaction.xid_state.rm_error= thd->get_stmt_da()->sql_errno(); +#ifdef WITH_WSREP + if (thd->is_error()) + { + WSREP_DEBUG("ha_rollback_trans(%lld, %s) rolled back: %s: %s; is_real %d", + thd->thread_id, all?"TRUE":"FALSE", WSREP_QUERY(thd), + thd->get_stmt_da()->message(), is_real_trans); + } + (void) wsrep_after_rollback(thd, all); +#endif /* Always cleanup. Even if nht==0. There may be savepoints. */ if (is_real_trans) { @@ -2296,6 +2372,14 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv) { int err; handlerton *ht= ha_info->ht(); +#ifdef WITH_WSREP + if (ht->db_type == DB_TYPE_INNODB) + { + WSREP_DEBUG("ha_rollback_to_savepoint: run before_rollbackha_rollback_trans hook"); + (void) wsrep_before_rollback(thd, !thd->in_sub_stmt); + + } +#endif // WITH_WSREP if ((err= ht->rollback(ht, thd, !thd->in_sub_stmt))) { // cannot happen my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err); @@ -6021,6 +6105,16 @@ static int binlog_log_row_internal(TABLE* table, bool error= 0; THD *const thd= table->in_use; +#ifdef WITH_WSREP + /* only InnoDB tables will be replicated through binlog emulation */ + if (WSREP_EMULATE_BINLOG(thd) && + table->file->ht->db_type != DB_TYPE_INNODB && + !(table->file->ht->db_type == DB_TYPE_PARTITION_DB && + (((ha_partition*)(table->file))->wsrep_db_type() == DB_TYPE_INNODB))) + { + return 0; + } +#endif /* WITH_WSREP */ /* If there are no table maps written to the binary log, this is the first row handled in this statement. In that case, we need @@ -6055,20 +6149,6 @@ int binlog_log_row(TABLE* table, const uchar *before_record, table->file->partition_ht()->db_type != DB_TYPE_INNODB) || (thd->wsrep_ignore_table == true)) return 0; - - /* enforce wsrep_max_ws_rows */ - if (WSREP(thd) && table->s->tmp_table == NO_TMP_TABLE) - { - thd->wsrep_affected_rows++; - if (wsrep_max_ws_rows && - thd->wsrep_exec_mode != REPL_RECV && - thd->wsrep_affected_rows > wsrep_max_ws_rows) - { - trans_rollback_stmt(thd) || trans_rollback(thd); - my_message(ER_ERROR_DURING_COMMIT, "wsrep_max_ws_rows exceeded", MYF(0)); - return ER_ERROR_DURING_COMMIT; - } - } #endif if (!table->file->check_table_binlog_row_based(1)) @@ -6180,6 +6260,31 @@ int handler::ha_reset() DBUG_RETURN(reset()); } +#ifdef WITH_WSREP +static int wsrep_after_row(THD *thd) +{ + DBUG_ENTER("wsrep_after_row"); + /* enforce wsrep_max_ws_rows */ + thd->wsrep_affected_rows++; + if (wsrep_max_ws_rows && + thd->wsrep_exec_mode != REPL_RECV && + thd->wsrep_affected_rows > wsrep_max_ws_rows) + { + trans_rollback_stmt(thd) || trans_rollback(thd); + my_message(ER_ERROR_DURING_COMMIT, "wsrep_max_ws_rows exceeded", MYF(0)); + DBUG_RETURN(ER_ERROR_DURING_COMMIT); + } + else if (wsrep_after_row(thd, false)) + { + if (!thd->get_stmt_da()->is_error()) + { + wsrep_override_error(thd, ER_LOCK_DEADLOCK); + } + DBUG_RETURN(ER_LOCK_DEADLOCK); + } + DBUG_RETURN(0); +} +#endif /* WITH_WSREP */ int handler::ha_write_row(uchar *buf) { @@ -6202,7 +6307,16 @@ int handler::ha_write_row(uchar *buf) { rows_changed++; error= binlog_log_row(table, 0, buf, log_func); +#ifdef WITH_WSREP + THD *thd= current_thd; + if (table_share->tmp_table == NO_TMP_TABLE && + WSREP(thd) && (error= wsrep_after_row(thd))) + { + DBUG_RETURN(error); + } +#endif /* WITH_WSREP */ } + DEBUG_SYNC_C("ha_write_row_end"); DBUG_RETURN(error); } @@ -6234,6 +6348,14 @@ int handler::ha_update_row(const uchar *old_data, const uchar *new_data) { rows_changed++; error= binlog_log_row(table, old_data, new_data, log_func); +#ifdef WITH_WSREP + THD *thd= current_thd; + if (table_share->tmp_table == NO_TMP_TABLE && + WSREP(thd) && (error= wsrep_after_row(thd))) + { + return error; + } +#endif /* WITH_WSREP */ } return error; } @@ -6289,6 +6411,14 @@ int handler::ha_delete_row(const uchar *buf) { rows_changed++; error= binlog_log_row(table, buf, 0, log_func); +#ifdef WITH_WSREP + THD *thd= current_thd; + if (table_share->tmp_table == NO_TMP_TABLE && + WSREP(thd) && (error= wsrep_after_row(thd))) + { + return error; + } +#endif /* WITH_WSREP */ } return error; } @@ -6494,51 +6624,15 @@ int ha_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal) DBUG_RETURN(0); } - void ha_fake_trx_id(THD *thd) { - DBUG_ENTER("ha_fake_trx_id"); - - bool no_fake_trx_id= true; - - if (!WSREP(thd)) - { - DBUG_VOID_RETURN; - } - - if (thd->wsrep_ws_handle.trx_id != WSREP_UNDEFINED_TRX_ID) + DBUG_ENTER("ha_wsrep_fake_trx_id"); + if (!WSREP(thd)) { - WSREP_DEBUG("fake trx id skipped: %lu", thd->wsrep_ws_handle.trx_id); DBUG_VOID_RETURN; } - /* Try statement transaction if standard one is not set. */ - THD_TRANS *trans= (thd->transaction.all.ha_list) ? &thd->transaction.all : - &thd->transaction.stmt; - - Ha_trx_info *ha_info= trans->ha_list, *ha_info_next; - - for (; ha_info; ha_info= ha_info_next) - { - handlerton *hton= ha_info->ht(); - if (hton->fake_trx_id) - { - hton->fake_trx_id(hton, thd); - - /* Got a fake trx id. */ - no_fake_trx_id= false; - - /* - We need transaction ID from just one storage engine providing - fake_trx_id (which will most likely be the case). - */ - break; - } - ha_info_next= ha_info->next(); - } - - if (unlikely(no_fake_trx_id)) - WSREP_WARN("Cannot get fake transaction ID from storage engine."); + (void *)wsrep_ws_handle_for_trx(&thd->wsrep_ws_handle, thd->query_id); DBUG_VOID_RETURN; } diff --git a/sql/item_create.cc b/sql/item_create.cc index d9b007d4728..f183076ad84 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -3193,6 +3193,45 @@ protected: }; #endif +#ifdef WITH_WSREP +class Create_func_wsrep_last_written_gtid : public Create_func_arg0 +{ +public: + virtual Item *create_builder(THD *thd); + + static Create_func_wsrep_last_written_gtid s_singleton; + +protected: + Create_func_wsrep_last_written_gtid() {} + virtual ~Create_func_wsrep_last_written_gtid() {} +}; + + +class Create_func_wsrep_last_seen_gtid : public Create_func_arg0 +{ +public: + virtual Item *create_builder(THD *thd); + + static Create_func_wsrep_last_seen_gtid s_singleton; + +protected: + Create_func_wsrep_last_seen_gtid() {} + virtual ~Create_func_wsrep_last_seen_gtid() {} +}; + + +class Create_func_wsrep_sync_wait_upto : public Create_native_func +{ +public: + virtual Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list); + + static Create_func_wsrep_sync_wait_upto s_singleton; + +protected: + Create_func_wsrep_sync_wait_upto() {} + virtual ~Create_func_wsrep_sync_wait_upto() {} +}; +#endif /* WITH_WSREP */ #ifdef HAVE_SPATIAL class Create_func_x : public Create_func_arg1 @@ -6886,6 +6925,63 @@ Create_func_within::create_2_arg(THD *thd, Item *arg1, Item *arg2) } #endif +#ifdef WITH_WSREP +Create_func_wsrep_last_written_gtid +Create_func_wsrep_last_written_gtid::s_singleton; + +Item* +Create_func_wsrep_last_written_gtid::create_builder(THD *thd) +{ + current_thd->lex->safe_to_cache_query= 0; + return new (thd->mem_root) Item_func_wsrep_last_written_gtid(thd); +} + + +Create_func_wsrep_last_seen_gtid +Create_func_wsrep_last_seen_gtid::s_singleton; + +Item* +Create_func_wsrep_last_seen_gtid::create_builder(THD *thd) +{ + current_thd->lex->safe_to_cache_query= 0; + return new (thd->mem_root) Item_func_wsrep_last_seen_gtid(thd); +} + + +Create_func_wsrep_sync_wait_upto +Create_func_wsrep_sync_wait_upto::s_singleton; + +Item* +Create_func_wsrep_sync_wait_upto::create_native(THD *thd, + LEX_CSTRING *name, + List<Item> *item_list) +{ + Item *func= NULL; + int arg_count= 0; + Item *param_1, *param_2; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) + { + case 1: + param_1= item_list->pop(); + func= new (thd->mem_root) Item_func_wsrep_sync_wait_upto(thd, param_1); + break; + case 2: + param_1= item_list->pop(); + param_2= item_list->pop(); + func= new (thd->mem_root) Item_func_wsrep_sync_wait_upto(thd, param_1, param_2); + break; + default: + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str); + break; + } + current_thd->lex->safe_to_cache_query= 0; + return func; +} +#endif /* WITH_WSREP */ #ifdef HAVE_SPATIAL Create_func_x Create_func_x::s_singleton; @@ -7328,7 +7424,11 @@ static Native_func_registry func_array[] = { { STRING_WITH_LEN("WEEKDAY") }, BUILDER(Create_func_weekday)}, { { STRING_WITH_LEN("WEEKOFYEAR") }, BUILDER(Create_func_weekofyear)}, { { STRING_WITH_LEN("WITHIN") }, GEOM_BUILDER(Create_func_within)}, - { { STRING_WITH_LEN("X") }, GEOM_BUILDER(Create_func_x)}, +#ifdef WITH_WSREP + { { STRING_WITH_LEN("WSREP_LAST_WRITTEN_GTID") }, BUILDER(Create_func_wsrep_last_written_gtid)}, + { { STRING_WITH_LEN("WSREP_LAST_SEEN_GTID") }, BUILDER(Create_func_wsrep_last_seen_gtid)}, + { { STRING_WITH_LEN("WSREP_SYNC_WAIT_UPTO_GTID") }, BUILDER(Create_func_wsrep_sync_wait_upto)}, +#endif /* WITH_WSREP */ { { STRING_WITH_LEN("X") }, GEOM_BUILDER(Create_func_x)}, { { STRING_WITH_LEN("Y") }, GEOM_BUILDER(Create_func_y)}, { { STRING_WITH_LEN("YEARWEEK") }, BUILDER(Create_func_year_week)}, diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 12618d68c27..38338174ae7 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -5264,3 +5264,105 @@ String *Item_temptable_rowid::val_str(String *str) str_value.set((char*)(table->file->ref), max_length, &my_charset_bin); return &str_value; } + +#ifdef WITH_WSREP + +#include "wsrep_mysqld.h" + +String * Item_func_wsrep_last_written_gtid::val_str_ascii(String *str) +{ + wsrep_gtid_t gtid; + wsrep_thd_last_written_gtid(current_thd, >id); + + if (gtid_str.alloc(WSREP_GTID_STR_LEN)) + { + my_error(ER_OUTOFMEMORY, WSREP_GTID_STR_LEN); + null_value= true; + return NULL; + } + int gtid_len = wsrep_gtid_print(>id, + (char*)gtid_str.ptr(), + WSREP_GTID_STR_LEN); + if (gtid_len < 0) + { + my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0), func_name(), + "wsrep_gtid_print failed"); + null_value= true; + return NULL; + } + gtid_str.length(gtid_len); + return >id_str; +} + +String * Item_func_wsrep_last_seen_gtid::val_str_ascii(String *str) +{ + wsrep_gtid_t gtid; + wsrep_last_committed_id(>id); + + if (gtid_str.alloc(WSREP_GTID_STR_LEN)) + { + my_error(ER_OUTOFMEMORY, WSREP_GTID_STR_LEN); + null_value= true; + return NULL; + } + int gtid_len= wsrep_gtid_print(>id, + (char*)gtid_str.ptr(), + WSREP_GTID_STR_LEN); + if (gtid_len < 0) + { + my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0), func_name(), + "wsrep_gtid_print failed"); + null_value= true; + return NULL; + } + gtid_str.length(gtid_len); + return >id_str; +} + +longlong Item_func_wsrep_sync_wait_upto::val_int() +{ + int timeout = -1; + String* gtid_str= args[0]->val_str(&value); + if (gtid_str == NULL) + { + my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name()); + return 0LL; + } + + if (arg_count == 2) + { + timeout = args[1]->val_int(); + } + + wsrep_gtid_t gtid; + int gtid_len= wsrep_gtid_scan(gtid_str->ptr(), gtid_str->length(), >id); + if (gtid_len < 0) + { + my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name()); + return 0LL; + } + + if (gtid.seqno == WSREP_SEQNO_UNDEFINED && + wsrep_uuid_compare(>id.uuid, &WSREP_UUID_UNDEFINED) == 0) + { + return 1LL; + } + + wsrep_status_t status= wsrep_sync_wait_upto(current_thd, >id, timeout); + + if (status != WSREP_OK) + { + int err; + switch (status) { + case WSREP_TRX_MISSING: + err= ER_WRONG_ARGUMENTS; + break; + default: + err= ER_LOCK_WAIT_TIMEOUT; + } + my_error(err, MYF(0), func_name()); + return 0LL; + } + return 1LL; +} +#endif /* WITH_WSREP */ diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 7c4ab93dc80..5fd13725b45 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -1805,4 +1805,56 @@ public: { return get_item_copy<Item_temptable_rowid>(thd, this); } }; +#ifdef WITH_WSREP + +#include "../wsrep/wsrep_api.h" + +class Item_func_wsrep_last_written_gtid: public Item_str_ascii_func +{ + String gtid_str; +public: + Item_func_wsrep_last_written_gtid(THD *thd): Item_str_ascii_func(thd) {} + const char *func_name() const { return "wsrep_last_written_gtid"; } + String *val_str_ascii(String *); + bool fix_length_and_dec() + { + max_length = WSREP_GTID_STR_LEN; + maybe_null = true; + return false; + } + Item *get_copy(THD *thd) + { return get_item_copy<Item_func_wsrep_last_written_gtid>(thd, this); } +}; + +class Item_func_wsrep_last_seen_gtid: public Item_str_ascii_func +{ + String gtid_str; +public: + Item_func_wsrep_last_seen_gtid(THD *thd): Item_str_ascii_func(thd) {} + const char *func_name() const { return "wsrep_last_seen_gtid"; } + String *val_str_ascii(String *); + bool fix_length_and_dec() + { + max_length = WSREP_GTID_STR_LEN; + maybe_null = true; + return false; + } + Item *get_copy(THD *thd) + { return get_item_copy<Item_func_wsrep_last_seen_gtid>(thd, this); } +}; + +class Item_func_wsrep_sync_wait_upto: public Item_int_func +{ + String value; +public: + Item_func_wsrep_sync_wait_upto(THD *thd, Item *a): Item_int_func(thd, a) {} + Item_func_wsrep_sync_wait_upto(THD *thd, Item *a, Item* b): Item_int_func(thd, a, b) {} + const Type_handler *type_handler() const { return &type_handler_string; } + const char *func_name() const { return "wsrep_sync_wait_upto_gtid"; } + longlong val_int(); + Item *get_copy(THD *thd) + { return get_item_copy<Item_func_wsrep_sync_wait_upto>(thd, this); } +}; +#endif /* WITH_WSREP */ + #endif /* ITEM_STRFUNC_INCLUDED */ diff --git a/sql/lock.cc b/sql/lock.cc index 17629f17291..3f0ceb259f4 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -1134,9 +1134,6 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd) make_global_read_lock_block_commit(), do nothing. */ - if (m_state != GRL_ACQUIRED) - DBUG_RETURN(0); - #ifdef WITH_WSREP if (WSREP(thd) && m_mdl_blocks_commits_lock) { @@ -1146,6 +1143,10 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd) } #endif /* WITH_WSREP */ + if (m_state != GRL_ACQUIRED) + DBUG_RETURN(0); + + mdl_request.init(MDL_key::COMMIT, "", "", MDL_SHARED, MDL_EXPLICIT); if (thd->mdl_context.acquire_lock(&mdl_request, @@ -1194,20 +1195,12 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd) } else if (ret != -ENOSYS) /* -ENOSYS - no provider */ { - long long ret = wsrep->pause(wsrep); - if (ret >= 0) - { - wsrep_locked_seqno= ret; - } - else if (ret != -ENOSYS) /* -ENOSYS - no provider */ - { - WSREP_ERROR("Failed to pause provider: %lld (%s)", -ret, strerror(-ret)); + WSREP_ERROR("Failed to pause provider: %lld (%s)", -ret, strerror(-ret)); - DBUG_ASSERT(m_mdl_blocks_commits_lock == NULL); - wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; - my_error(ER_LOCK_DEADLOCK, MYF(0)); - DBUG_RETURN(TRUE); - } + DBUG_ASSERT(m_mdl_blocks_commits_lock == NULL); + wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; + my_error(ER_LOCK_DEADLOCK, MYF(0)); + DBUG_RETURN(TRUE); } #endif /* WITH_WSREP */ DBUG_RETURN(FALSE); diff --git a/sql/log.cc b/sql/log.cc index 6975b58dfb7..1199cab5c78 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -59,6 +59,8 @@ #include "sp_rcontext.h" #include "sp_head.h" +#include "wsrep_trans_observer.h" + /* max size of the log message */ #define MAX_LOG_BUFFER_SIZE 1024 #define MAX_TIME_SIZE 32 @@ -406,8 +408,49 @@ public: Cache to store data before copying it to the binary log. */ IO_CACHE cache_log; +#ifdef WITH_WSREP + void wsrep_reset_fragment_base(ulong size) + { + wsrep_fragment_base = size; + } + + void wsrep_reset_fragment_fill(ulong size) + { + wsrep_fragment_fill = size; + } + + void wsrep_reset_SR_trans() + { + wsrep_reset_fragment_fill(0); + wsrep_reset_fragment_base(0); + } + + ulong wsrep_get_fragment_fill() + { + return (wsrep_fragment_fill); + } + + void wsrep_append_fill_rate(ulong size) + { + wsrep_fragment_fill += size; + } + + void wsrep_step_fragment_base(ulong size) + { + wsrep_fragment_base += size; + } + ulong wsrep_get_fragment_base() + { + return(wsrep_fragment_base); + } +#endif /* WITH_WSREP */ private: +#ifdef WITH_WSREP + ulong wsrep_fragment_fill; + ulong wsrep_fragment_base; +#endif /* WITH_WSREP */ + /* Pending binrows event. This event is the event where the rows are currently written. @@ -533,6 +576,9 @@ public: using_xa= FALSE; last_commit_pos_file[0]= 0; last_commit_pos_offset= 0; +#ifdef WITH_WSREP + trx_cache.wsrep_reset_SR_trans(); +#endif /* WITH_WSREP */ } } @@ -1699,7 +1745,8 @@ static int binlog_close_connection(handlerton *hton, THD *thd) (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); #ifdef WITH_WSREP if (cache_mngr && !cache_mngr->trx_cache.empty()) { - IO_CACHE* cache= get_trans_log(thd); + //IO_CACHE* cache= wsrep_get_trans_cache(thd); + IO_CACHE* cache= cache_mngr->get_binlog_cache_log(true); uchar *buf; size_t len=0; wsrep_write_cache_buf(cache, &buf, &len); @@ -2293,8 +2340,17 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv) non-transactional table. Otherwise, truncate the binlog cache starting from the SAVEPOINT command. */ +#ifdef WITH_WSREP + /* for streaming replication, we must replicate savepoint rollback so that + slaves can maintain SR transactions + */ + if (unlikely(thd->wsrep_is_streaming() || + (trans_has_updated_non_trans_table(thd)) || + (thd->variables.option_bits & OPTION_KEEP_LOG))) +#else if (unlikely(trans_has_updated_non_trans_table(thd) || (thd->variables.option_bits & OPTION_KEEP_LOG))) +#endif /* WITH_WSREP */ { char buf[1024]; String log_query(buf, sizeof(buf), &my_charset_bin); @@ -7699,7 +7755,30 @@ MYSQL_BIN_LOG::write_transaction_to_binlog_events(group_commit_entry *entry) DEBUG_SYNC(entry->thd, "commit_loop_entry_commit_ordered"); ++num_commits; if (entry->cache_mngr->using_xa && !entry->error) +#ifdef WITH_WSREP + { + if (WSREP(entry->thd) && entry->thd->wsrep_trx_must_order_commit() && + wsrep_before_commit(entry->thd, entry->all)) + { + return (true); + } +#endif /* WITH_WSREP */ run_commit_ordered(entry->thd, entry->all); +#ifdef WITH_WSREP + if (WSREP(entry->thd) && entry->thd->wsrep_trx_must_order_commit()) + { + /* + TODO: Ordered commit should be done after the transaction + has been queued for group commit. + */ + int error= wsrep_ordered_commit(entry->thd, entry->all, wsrep_apply_error()); + if (!error) + { + (void) wsrep_after_commit(entry->thd, entry->all); + } + } + } +#endif /* WITH_WSREP */ group_commit_entry *next= entry->next; if (!next) @@ -8083,7 +8162,31 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader) ++num_commits; if (current->cache_mngr->using_xa && likely(!current->error) && DBUG_EVALUATE_IF("skip_commit_ordered", 0, 1)) +#ifdef WITH_WSREP + { + if (WSREP(current->thd) && current_thd->wsrep_trx_must_order_commit() && + wsrep_before_commit(current->thd, current->all)) + { + DBUG_VOID_RETURN; + } +#endif /* WITH_WSREP */ run_commit_ordered(current->thd, current->all); +#ifdef WITH_WSREP + if (WSREP(current->thd) && current_thd->wsrep_trx_must_order_commit()) + { + /* + TODO: Ordered commit should be done after the transaction + has been queued for group commit. + */ + int error= wsrep_ordered_commit(current->thd, current->all, wsrep_apply_error()); + //if (!error) (void) wsrep_after_commit(current->thd, current->all); + if (!error) + { + (void) wsrep_after_commit(current->thd, current->all); + } + } + } +#endif /* WITH_WSREP */ current->thd->wakeup_subsequent_commits(current->error); /* @@ -8923,9 +9026,31 @@ int TC_LOG_MMAP::log_and_order(THD *thd, my_xid xid, bool all, /* Only run commit_ordered() if log_xid was successful. */ if (cookie) { +#ifdef WITH_WSREP + if (WSREP(thd) && thd->wsrep_trx_must_order_commit() && + wsrep_before_commit(thd, all)) + { + return(0); + } +#endif /* WITH_WSREP */ mysql_mutex_lock(&LOCK_commit_ordered); run_commit_ordered(thd, all); mysql_mutex_unlock(&LOCK_commit_ordered); +#ifdef WITH_WSREP + //if (WSREP(thd) && !thd->wsrep_apply_toi) + if (WSREP(thd) && thd->wsrep_trx_must_order_commit()) + { + /* + TODO: Ordered commit should be done after the transaction + has been queued for group commit. + */ + int error= wsrep_ordered_commit(thd, all, wsrep_apply_error()); + if (!error) + { + (void) wsrep_after_commit(thd, all); + } + } +#endif /* WITH_WSREP */ } if (need_prepare_ordered) @@ -9623,6 +9748,30 @@ TC_LOG_BINLOG::log_and_order(THD *thd, my_xid xid, bool all, if (err) DBUG_RETURN(0); +#ifdef WITH_WSREP + if (WSREP(thd) && thd->wsrep_exec_mode != REPL_RECV && + thd->wsrep_trx_must_order_commit() && + wsrep_before_commit(thd, all)) + { + return(0); + } +#endif /* WITH_WSREP */ +#ifdef WITH_WSREP + //if (WSREP(thd) && !thd->wsrep_apply_toi) + if (WSREP(thd) && thd->wsrep_exec_mode != REPL_RECV && + thd->wsrep_trx_must_order_commit()) + { + /* + TODO: Ordered commit should be done after the transaction + has been queued for group commit. + */ + int error= wsrep_ordered_commit(thd, all, wsrep_apply_error()); + if (!error) + { + (void) wsrep_after_commit(thd, all); + } + } +#endif /* WITH_WSREP */ bool need_unlog= cache_mngr->need_unlog; /* @@ -10589,7 +10738,44 @@ maria_declare_plugin(binlog) maria_declare_plugin_end; #ifdef WITH_WSREP -IO_CACHE * get_trans_log(THD * thd) +#include "wsrep_trans_observer.h" +#include "wsrep_mysqld.h" + +static int wsrep_plugin_init(void *p) +{ + WSREP_INFO("wsrep_plugin_init()"); + return wsrep_register_trans_observer(p); +} + +static int wsrep_plugin_deinit(void *p) +{ + WSREP_INFO("wsrep_plugin_deinit()"); + return wsrep_unregister_trans_observer(p); +} + +struct Mysql_replication wsrep_plugin= { + MYSQL_REPLICATION_INTERFACE_VERSION +}; + +maria_declare_plugin(wsrep) +{ + MYSQL_REPLICATION_PLUGIN, + &wsrep_plugin, + "wsrep", + "Codership Oy", + "Wsrep replication plugin", + PLUGIN_LICENSE_GPL, + wsrep_plugin_init, + wsrep_plugin_deinit, + 0x0100, + NULL, /* Status variables */ + NULL, /* System variables */ + "1.0", /* Version (string) */ + MariaDB_PLUGIN_MATURITY_STABLE /* Maturity */ +} +maria_declare_plugin_end; + +IO_CACHE *wsrep_get_trans_cache(THD * thd) { DBUG_ASSERT(binlog_hton->slot != HA_SLOT_UNDEF); binlog_cache_mngr *cache_mngr = (binlog_cache_mngr*) @@ -10603,15 +10789,115 @@ IO_CACHE * get_trans_log(THD * thd) } -bool wsrep_trans_cache_is_empty(THD *thd) +uint wsrep_get_trans_cache_position(THD *thd) { + if (binlog_hton) + { + my_off_t pos = 0; + binlog_cache_mngr *const cache_mngr= (binlog_cache_mngr*) + thd_get_ha_data(thd, binlog_hton); + if (cache_mngr) binlog_trans_log_savepos(thd, &pos); + return (pos); + } + return 0; +} + +void wsrep_reset_SR_trans(THD *thd) +{ + DBUG_ENTER("wsrep_reset_SR_trans"); + if (!binlog_hton || !WSREP(thd)) DBUG_VOID_RETURN; + thd->wsrep_fragments_sent = 0; + binlog_cache_mngr *const cache_mngr= - (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); - return (!cache_mngr || cache_mngr->trx_cache.empty()); + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + if (cache_mngr) + { + cache_mngr->trx_cache.wsrep_reset_fragment_base(0); + cache_mngr->trx_cache.wsrep_reset_fragment_fill(0); + } + DBUG_VOID_RETURN; +} + +void wsrep_step_fragment_base(THD *thd, ulong size) +{ + DBUG_ASSERT(binlog_hton && WSREP(thd) && + thd->variables.wsrep_trx_fragment_size > 0); + if (!binlog_hton || !WSREP(thd) || + thd->variables.wsrep_trx_fragment_size == 0) return; + + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + + if (cache_mngr) + { + cache_mngr->trx_cache.wsrep_step_fragment_base(size); + } +} + +ulong wsrep_get_fragment_base(THD *thd) +{ + if (!binlog_hton || !WSREP(thd)) return 0; + + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + + + if (cache_mngr) + { + return cache_mngr->trx_cache.wsrep_get_fragment_base(); + } + return 0; +} +void wsrep_append_fill_rate(THD *thd, ulong size) +{ + DBUG_ASSERT(binlog_hton && WSREP(thd) && + thd->variables.wsrep_trx_fragment_size > 0); + if (!binlog_hton || !WSREP(thd) || + thd->variables.wsrep_trx_fragment_size == 0) return; + + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + + if (cache_mngr) + { + cache_mngr->trx_cache.wsrep_append_fill_rate(size); + } +} + +void wsrep_reset_fragment_fill(THD *thd, ulong size) +{ + DBUG_ASSERT(binlog_hton && WSREP(thd) && + thd->variables.wsrep_trx_fragment_size > 0); + if (!binlog_hton || !WSREP(thd) || + thd->variables.wsrep_trx_fragment_size == 0) return; + + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + + if (cache_mngr) + { + cache_mngr->trx_cache.wsrep_reset_fragment_fill(size); + } } +ulong wsrep_get_fragment_fill(THD *thd) +{ + DBUG_ASSERT(binlog_hton && WSREP(thd) && + thd->variables.wsrep_trx_fragment_size > 0); + if (!binlog_hton || !WSREP(thd) || + thd->variables.wsrep_trx_fragment_size == 0) return 0; -void thd_binlog_trx_reset(THD * thd) + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + + if (cache_mngr) + { + return cache_mngr->trx_cache.wsrep_get_fragment_fill(); + } + return 0; +} + +void wsrep_thd_binlog_trx_reset(THD * thd) { /* todo: fix autocommit select to not call the caller @@ -10643,4 +10929,85 @@ void thd_binlog_rollback_stmt(THD * thd) if (cache_mngr) cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF); } + +int wsrep_thd_binlog_prepare(THD* thd, bool all) +{ + /* applier and replayer can skip binlog prepare */ + if (WSREP_EMULATE_BINLOG(thd) && (thd->wsrep_exec_mode != REPL_RECV)) + return binlog_hton->prepare(binlog_hton, thd, all); + else + return ha_prepare(thd); +} + +bool wsrep_stmt_rollback_is_safe(THD* thd) +{ + bool ret(true); + + DBUG_ENTER("wsrep_binlog_stmt_rollback_is_safe"); + + binlog_cache_mngr *cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + + + if (binlog_hton && cache_mngr) + { + binlog_cache_data * trx_cache = &cache_mngr->trx_cache; + if (thd->wsrep_fragments_sent > 0 && + (trx_cache->get_prev_position() == MY_OFF_T_UNDEF || + trx_cache->get_prev_position() < trx_cache->wsrep_get_fragment_base())) + { + WSREP_DEBUG("statement rollback is not safe for streaming replication" + " pre-stmt_pos: %llu, frag repl pos: %lu\nThread: %llu, SQL: %s", + trx_cache->get_prev_position(), trx_cache->wsrep_get_fragment_base(), + thd->thread_id, thd->query()); + ret = false; + } + } + DBUG_RETURN(ret); +} + +void wsrep_register_binlog_handler(THD *thd, bool trx) +{ + DBUG_ENTER("register_binlog_handler"); + /* + If this is the first call to this function while processing a statement, + the transactional cache does not have a savepoint defined. So, in what + follows: + . an implicit savepoint is defined; + . callbacks are registered; + . binary log is set as read/write. + + The savepoint allows for truncating the trx-cache transactional changes + fail. Callbacks are necessary to flush caches upon committing or rolling + back a statement or a transaction. However, notifications do not happen + if the binary log is set as read/write. + */ + //binlog_cache_mngr *cache_mngr= thd_get_cache_mngr(thd); + binlog_cache_mngr *cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + /* cache_mngr may be missing e.g. in mtr test ev51914.test */ + if (cache_mngr && cache_mngr->trx_cache.get_prev_position() == MY_OFF_T_UNDEF) + { + /* + Set an implicit savepoint in order to be able to truncate a trx-cache. + */ + my_off_t pos= 0; + binlog_trans_log_savepos(thd, &pos); + cache_mngr->trx_cache.set_prev_position(pos); + + /* + Set callbacks in order to be able to call commmit or rollback. + */ + if (trx) + trans_register_ha(thd, TRUE, binlog_hton); + trans_register_ha(thd, FALSE, binlog_hton); + + /* + Set the binary log as read/write otherwise callbacks are not called. + */ + thd->ha_data[binlog_hton->slot].ha_info[0].set_trx_read_write(); + } + DBUG_VOID_RETURN; +} + #endif /* WITH_WSREP */ diff --git a/sql/log.h b/sql/log.h index 7dfdb36c442..1aa83eaabb1 100644 --- a/sql/log.h +++ b/sql/log.h @@ -96,6 +96,11 @@ extern PSI_mutex_key key_LOCK_prepare_ordered, key_LOCK_commit_ordered; extern PSI_mutex_key key_LOCK_after_binlog_sync; extern PSI_cond_key key_COND_prepare_ordered; #endif +#ifdef WITH_WSREP +int wsrep_thd_binlog_commit(THD *thd, bool all); +int wsrep_thd_binlog_rollback(THD *thd, bool all); +int wsrep_thd_binlog_prepare(THD *thd, bool all); +#endif /* WITH_WSREP */ class TC_LOG_DUMMY: public TC_LOG // use it to disable the logging { @@ -103,6 +108,11 @@ public: TC_LOG_DUMMY() {} int open(const char *opt_name) { return 0; } void close() { } +#ifdef WITH_WSREP + int commit(THD *thd, bool all) { + return wsrep_thd_binlog_commit(thd, all); + } +#endif /* WITH_WSREP */ /* TC_LOG_DUMMY is only used when there are <= 1 XA-capable engines, and we only use internal XA during commit when >= 2 XA-capable engines @@ -1211,6 +1221,15 @@ static inline TC_LOG *get_tc_log_implementation() return &mysql_bin_log; return &tc_log_mmap; } +#ifdef WITH_WSREP +IO_CACHE* wsrep_get_trans_cache(THD *); +void wsrep_thd_binlog_trx_reset(THD * thd); +#define WSREP_BINLOG_FORMAT(my_format) \ + ((wsrep_forced_binlog_format != BINLOG_FORMAT_UNSPEC) ? \ + wsrep_forced_binlog_format : my_format) +#else +#define WSREP_BINLOG_FORMAT(my_format) my_format +#endif /* WITH_WSREP */ class Gtid_list_log_event; diff --git a/sql/log_event.cc b/sql/log_event.cc index 13690a8be60..cfbf0a2232c 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -5743,6 +5743,14 @@ compare_errors: "unexpected success or fatal error"), thd->get_db(), query_arg); thd->is_slave_error= 1; +#ifdef WITH_WSREP + if (thd->wsrep_apply_toi && wsrep_must_ignore_error(thd)) + { + thd->clear_error(1); + thd->killed= NOT_KILLED; + thd->wsrep_has_ignored_error= true; + } +#endif /* WITH_WSREP */ } /* @@ -11264,10 +11272,10 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) thd->get_stmt_da()->sql_errno(), thd->is_fatal_error, thd->wsrep_exec_mode, - thd->wsrep_conflict_state, + thd->wsrep_conflict_state_unsafe(), (long long)wsrep_thd_trx_seqno(thd)); } -#endif +#endif /* WITH_WSREP */ if ((thd->is_slave_error || thd->is_fatal_error) && !is_parallel_retry_error(rgi, actual_error)) { @@ -11520,6 +11528,13 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) bool ignored_error= (idempotent_error == 0 ? ignored_error_code(actual_error) : 0); +#ifdef WITH_WSREP + if (WSREP(thd) && wsrep_ignored_error_code(this, actual_error)) + { + idempotent_error= true; + thd->wsrep_has_ignored_error= true; + } +#endif /* WITH_WSREP */ if (idempotent_error || ignored_error) { if (global_system_variables.log_warnings) diff --git a/sql/mdl.cc b/sql/mdl.cc index f03fc89fcc1..cc06d5ef336 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -1073,7 +1073,7 @@ MDL_wait::timed_wait(MDL_context_owner *owner, struct timespec *abs_timeout, thd_wait_begin(NULL, THD_WAIT_META_DATA_LOCK); while (!m_wait_status && !owner->is_killed() && wait_result != ETIMEDOUT && wait_result != ETIME) - { + { #ifdef WITH_WSREP // Allow tests to block the applier thread using the DBUG facilities DBUG_EXECUTE_IF("sync.wsrep_before_mdl_wait", @@ -1084,7 +1084,7 @@ MDL_wait::timed_wait(MDL_context_owner *owner, struct timespec *abs_timeout, DBUG_ASSERT(!debug_sync_set_action((owner->get_thd()), STRING_WITH_LEN(act))); };); - if (wsrep_thd_is_BF(owner->get_thd(), false)) + if (wsrep_thd_is_BF((void*)owner->get_thd(), false)) { wait_result= mysql_cond_wait(&m_COND_wait_status, &m_LOCK_wait_status); } @@ -1158,19 +1158,19 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket) DBUG_ASSERT(ticket->get_lock()); #ifdef WITH_WSREP if ((this == &(ticket->get_lock()->m_waiting)) && - wsrep_thd_is_BF(ticket->get_ctx()->get_thd(), false)) + wsrep_thd_is_BF((void*)ticket->get_ctx()->get_thd(), false)) { Ticket_iterator itw(ticket->get_lock()->m_waiting); Ticket_iterator itg(ticket->get_lock()->m_granted); DBUG_ASSERT(WSREP_ON); - MDL_ticket *waiting, *granted; + MDL_ticket *waiting; MDL_ticket *prev=NULL; bool added= false; while ((waiting= itw++) && !added) { - if (!wsrep_thd_is_BF(waiting->get_ctx()->get_thd(), true)) + if (!wsrep_thd_is_BF((void*)waiting->get_ctx()->get_thd(), true)) { WSREP_DEBUG("MDL add_ticket inserted before: %lu %s", thd_get_thread_id(waiting->get_ctx()->get_thd()), @@ -1185,18 +1185,6 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket) /* Otherwise, insert the ticket at the back of the waiting list. */ if (!added) m_list.push_back(ticket); - while ((granted= itg++)) - { - if (granted->get_ctx() != ticket->get_ctx() && - granted->is_incompatible_when_granted(ticket->get_type())) - { - if (!wsrep_grant_mdl_exception(ticket->get_ctx(), granted, - &ticket->get_lock()->key)) - { - WSREP_DEBUG("MDL victim killed at add_ticket"); - } - } - } } else #endif /* WITH_WSREP */ @@ -1558,7 +1546,6 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg, bool can_grant= FALSE; bitmap_t waiting_incompat_map= incompatible_waiting_types_bitmap()[type_arg]; bitmap_t granted_incompat_map= incompatible_granted_types_bitmap()[type_arg]; - bool wsrep_can_grant= TRUE; /* New lock request can be satisfied iff: @@ -1571,10 +1558,20 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg, { if (! (m_granted.bitmap() & granted_incompat_map)) can_grant= TRUE; +#ifdef WITH_WSREP + else if (wsrep_thd_is_BF((void *)(requestor_ctx->get_thd()),false) && + key.mdl_namespace() == MDL_key::GLOBAL) + { + WSREP_DEBUG("global lock granted for BF: %lld %s", + wsrep_thd_thread_id(requestor_ctx->get_thd()), + wsrep_thd_query(requestor_ctx->get_thd())); + can_grant= TRUE; + } else { Ticket_iterator it(m_granted); MDL_ticket *ticket; + bool wsrep_can_grant= TRUE; /* Check that the incompatible lock belongs to some other context. */ while ((ticket= it++)) @@ -1582,16 +1579,7 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg, if (ticket->get_ctx() != requestor_ctx && ticket->is_incompatible_when_granted(type_arg)) { -#ifdef WITH_WSREP - if (wsrep_thd_is_BF(requestor_ctx->get_thd(),false) && - key.mdl_namespace() == MDL_key::GLOBAL) - { - WSREP_DEBUG("global lock granted for BF: %lu %s", - thd_get_thread_id(requestor_ctx->get_thd()), - wsrep_thd_query(requestor_ctx->get_thd())); - can_grant = true; - } - else if (!wsrep_grant_mdl_exception(requestor_ctx, ticket, &key)) + if (!wsrep_grant_mdl_exception(requestor_ctx, ticket, &key)) { wsrep_can_grant= FALSE; if (wsrep_log_conflicts) @@ -1603,21 +1591,33 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg, "abort" ); } } - else - can_grant= TRUE; - /* Continue loop */ + } + } + if (wsrep_can_grant) + can_grant= TRUE; + } #else + else + { + Ticket_iterator it(m_granted); + MDL_ticket *ticket; + + /* Check that the incompatible lock belongs to some other context. */ + while ((ticket= it++)) + { + if (ticket->get_ctx() != requestor_ctx && + ticket->is_incompatible_when_granted(type_arg)) break; -#endif /* WITH_WSREP */ - } } - if ((ticket == NULL) && wsrep_can_grant) - can_grant= TRUE; /* Incompatible locks are our own. */ + if (ticket == NULL) /* Incompatible locks are our own. */ + can_grant= TRUE; } +#endif /* WITH_WSREP */ } +#ifdef WITH_WSREP else { - if (wsrep_thd_is_BF(requestor_ctx->get_thd(), false) && + if (wsrep_thd_is_BF((void*)requestor_ctx->get_thd(), false) && key.mdl_namespace() == MDL_key::GLOBAL) { WSREP_DEBUG("global lock granted for BF (waiting queue): %lu %s", @@ -1626,6 +1626,8 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg, can_grant = true; } } +#endif /* WITH_WSREP */ + return can_grant; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index ce14dc678c6..d3b9ab03640 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1604,7 +1604,6 @@ ATTRIBUTE_NORETURN static void mysqld_exit(int exit_code); static void delete_pid_file(myf flags); static void end_ssl(); - #ifndef EMBEDDED_LIBRARY /**************************************************************************** ** Code to end mysqld @@ -1733,6 +1732,7 @@ static void close_connections(void) #endif tmp->set_killed(KILL_SERVER_HARD); MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp)); + if (WSREP(tmp)) mysql_mutex_lock(&tmp->LOCK_wsrep_thd); mysql_mutex_lock(&tmp->LOCK_thd_kill); if (tmp->mysys_var) { @@ -1757,6 +1757,7 @@ static void close_connections(void) mysql_mutex_unlock(&tmp->mysys_var->mutex); } mysql_mutex_unlock(&tmp->LOCK_thd_kill); + if (WSREP(tmp)) mysql_mutex_unlock(&tmp->LOCK_wsrep_thd); } mysql_mutex_unlock(&LOCK_thread_count); // For unlink from list @@ -1842,6 +1843,10 @@ static void close_connections(void) mysql_mutex_unlock(&LOCK_thread_count); } end_slave(); +#ifdef WITH_WSREP + if (wsrep_inited == 1) + wsrep_deinit(true); +#endif /* All threads has now been aborted */ DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count)); mysql_mutex_lock(&LOCK_thread_count); @@ -2028,7 +2033,7 @@ static void __cdecl kill_server(int sig_ptr) /* Stop wsrep threads in case they are running. */ if (wsrep_running_threads > 0) { - wsrep_stop_replication(NULL); + wsrep_shutdown_replication(); } close_connections(); @@ -2140,10 +2145,14 @@ extern "C" void unireg_abort(int exit_code) if (wsrep) { /* + Signal SE init waiters to exit with error status + */ + wsrep_SE_init_failed(); + /* This is an abort situation, we cannot expect to gracefully close all wsrep threads here, we can only diconnect from service */ - wsrep_close_client_connections(FALSE); + wsrep_close_client_connections(FALSE, NULL); shutdown_in_progress= 1; wsrep->disconnect(wsrep); WSREP_INFO("Service disconnected."); @@ -2930,6 +2939,14 @@ void signal_thd_deleted() mysql_cond_broadcast(&COND_thread_count); mysql_mutex_unlock(&LOCK_thread_count); } + else + { + /* Naah, I signal anyways */ + WSREP_DEBUG("forced signal for COND_thread_count"); + mysql_mutex_lock(&LOCK_thread_count); + mysql_cond_broadcast(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); + } } @@ -5330,6 +5347,15 @@ static int init_server_components() } } + if (WSREP_NOT_SPECIFIED) + { + // enable normal operation in case no provider is specified +#ifndef EMBEDDED_LIBRARY + wsrep_ready_set(TRUE); +#endif + global_system_variables.wsrep_on = 0; + } + if (opt_bin_log) { if (mysql_bin_log.open_index_file(opt_binlog_index_name, opt_bin_logname, @@ -6092,10 +6118,7 @@ int mysqld_main(int argc, char **argv) wsrep_SE_init_grab(); wsrep_SE_init_done(); /*! in case of SST wsrep waits for wsrep->sst_received */ - if (wsrep_sst_continue()) - { - WSREP_ERROR("Failed to signal the wsrep provider to continue."); - } + wsrep_sst_continue(); } else { @@ -8752,6 +8775,20 @@ SHOW_VAR status_vars[]= { {"Uptime_since_flush_status",(char*) &show_flushstatustime, SHOW_SIMPLE_FUNC}, #endif #ifdef WITH_WSREP + {"wsrep_connected", (char*) &wsrep_connected, SHOW_BOOL}, + {"wsrep_ready", (char*) &wsrep_show_ready, SHOW_FUNC}, + {"wsrep_cluster_state_uuid",(char*) &wsrep_cluster_state_uuid,SHOW_CHAR_PTR}, + {"wsrep_cluster_conf_id", (char*) &wsrep_cluster_conf_id, SHOW_LONGLONG}, + {"wsrep_cluster_status", (char*) &wsrep_cluster_status, SHOW_CHAR_PTR}, + {"wsrep_cluster_size", (char*) &wsrep_cluster_size, SHOW_LONG_NOFLUSH}, + {"wsrep_local_index", (char*) &wsrep_local_index, SHOW_LONG_NOFLUSH}, + {"wsrep_local_bf_aborts", (char*) &wsrep_show_bf_aborts, SHOW_FUNC}, + {"wsrep_provider_name", (char*) &wsrep_provider_name, SHOW_CHAR_PTR}, + {"wsrep_provider_version", (char*) &wsrep_provider_version, SHOW_CHAR_PTR}, + {"wsrep_provider_vendor", (char*) &wsrep_provider_vendor, SHOW_CHAR_PTR}, + {"wsrep_provider_capabilities", (char*) &wsrep_provider_capabilities, SHOW_CHAR_PTR}, + {"wsrep_thread_count", (char*) &wsrep_running_threads, SHOW_LONG_NOFLUSH}, + {"wsrep_cluster_capabilities", (char*) &wsrep_cluster_capabilities, SHOW_CHAR_PTR}, {"wsrep", (char*) &wsrep_show_status, SHOW_FUNC}, #endif {NullS, NullS, SHOW_LONG} diff --git a/sql/protocol.cc b/sql/protocol.cc index 29004fe24e4..d370ff38e4a 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -551,8 +551,25 @@ static uchar *net_store_length_fast(uchar *packet, size_t length) void Protocol::end_statement() { - /* sanity check*/ - DBUG_ASSERT_IF_WSREP(!(WSREP(thd) && thd->wsrep_conflict_state == REPLAYING)); + /* + Commented out: This sanity check does not hold in general. + Thd->LOCK_wsrep_thd() must be unlocked before sending response + to client, so BF abort may sneak in here. + DBUG_ASSERT(!WSREP(thd) || thd->wsrep_conflict_state() == NO_CONFLICT); + */ + + /* + sanity check, don't send end statement while replaying + */ +#ifdef WITH_WSREP + DBUG_ASSERT(thd->wsrep_conflict_state_unsafe() != REPLAYING); + if (WSREP(thd) && thd->wsrep_conflict_state_unsafe()== REPLAYING) + { + WSREP_ERROR("attempting net_end_statement while replaying"); + return; + } +#endif + DBUG_ENTER("Protocol::end_statement"); DBUG_ASSERT(! thd->get_stmt_da()->is_sent()); bool error= FALSE; diff --git a/sql/slave.cc b/sql/slave.cc index bb1300d36e6..20e9cfb3a32 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3917,14 +3917,19 @@ apply_event_and_update_pos_apply(Log_event* ev, THD* thd, rpl_group_info *rgi, exec_res= ev->apply_event(rgi); #ifdef WITH_WSREP - if (exec_res && thd->wsrep_conflict_state != NO_CONFLICT) + if (WSREP_ON) + { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (exec_res && thd->wsrep_conflict_state() != NO_CONFLICT) { WSREP_DEBUG("SQL apply failed, res %d conflict state: %d", - exec_res, thd->wsrep_conflict_state); + exec_res, thd->wsrep_conflict_state_unsafe()); rli->abort_slave= 1; rli->report(ERROR_LEVEL, ER_UNKNOWN_COM_ERROR, rgi->gtid_info(), "Node has dropped from cluster"); } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } #endif #ifndef DBUG_OFF @@ -4217,6 +4222,11 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, } if (ev) { +#ifdef WITH_WSREP + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_EXEC); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); +#endif /* WITH_WSREP */ int exec_res; Log_event_type typ= ev->get_type_code(); @@ -4261,6 +4271,11 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, rli->abort_slave= 1; rli->stop_for_until= true; mysql_mutex_unlock(&rli->data_lock); +#ifdef WITH_WSREP + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_IDLE); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); +#endif /* WITH_WSREP */ delete ev; DBUG_RETURN(1); } @@ -4298,7 +4313,16 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, if (res == 0) rli->event_relay_log_pos= rli->future_event_relay_log_pos; if (res >= 0) +#ifdef WITH_WSREP + { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_IDLE); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); +#endif /* WITH_WSREP */ DBUG_RETURN(res); +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ /* Else we proceed to execute the event non-parallel. This is the case for pre-10.0 events without GTID, and for handling @@ -4320,6 +4344,11 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, "aborted because of out-of-memory error"); mysql_mutex_unlock(&rli->data_lock); delete ev; +#ifdef WITH_WSREP + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_IDLE); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); +#endif /* WITH_WSREP */ DBUG_RETURN(1); } @@ -4334,6 +4363,11 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, "thread aborted because of out-of-memory error"); mysql_mutex_unlock(&rli->data_lock); delete ev; +#ifdef WITH_WSREP + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_IDLE); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); +#endif /* WITH_WSREP */ DBUG_RETURN(1); } /* @@ -4362,13 +4396,19 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, retry. */ if (unlikely(exec_res == 2)) +#ifdef WITH_WSREP + { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_IDLE); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); +#endif /* WITH_WSREP */ DBUG_RETURN(1); - #ifdef WITH_WSREP - mysql_mutex_lock(&thd->LOCK_thd_data); - if (thd->wsrep_conflict_state == NO_CONFLICT) + } + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state() == NO_CONFLICT) { - mysql_mutex_unlock(&thd->LOCK_thd_data); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); #endif /* WITH_WSREP */ if (slave_trans_retries) { @@ -4446,10 +4486,15 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, #ifdef WITH_WSREP } else - mysql_mutex_unlock(&thd->LOCK_thd_data); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); #endif /* WITH_WSREP */ thread_safe_increment64(&rli->executed_entries); +#ifdef WITH_WSREP + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_IDLE); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); +#endif /* WITH_WSREP */ DBUG_RETURN(exec_res); } mysql_mutex_unlock(&rli->data_lock); @@ -5515,10 +5560,16 @@ pthread_handler_t handle_slave_sql(void *arg) if (exec_relay_log_event(thd, rli, serial_rgi)) { #ifdef WITH_WSREP - if (thd->wsrep_conflict_state != NO_CONFLICT) + if (WSREP_ON) { - wsrep_node_dropped= TRUE; - rli->abort_slave= TRUE; + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + + if (thd->wsrep_conflict_state() != NO_CONFLICT) + { + wsrep_node_dropped= TRUE; + rli->abort_slave= TRUE; + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); } #endif /* WITH_WSREP */ @@ -5550,6 +5601,9 @@ pthread_handler_t handle_slave_sql(void *arg) sql_print_information("Slave SQL thread exiting, replication stopped in " "log '%s' at position %llu%s", RPL_LOG_NAME, rli->group_master_log_pos, tmp.c_ptr_safe()); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + WSREP_DEBUG("SQL thread %lu exec %d query state %d", thd->thread_id, thd->wsrep_exec_mode , thd->wsrep_query_state()); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); } err_before_start: @@ -5662,24 +5716,25 @@ err_during_init: trigger automatic restart of slave when node joins back to cluster. */ if (WSREP_ON && wsrep_node_dropped && wsrep_restart_slave) - { - if (wsrep_ready_get()) - { - WSREP_INFO("Slave error due to node temporarily non-primary" - "SQL slave will continue"); - wsrep_node_dropped= FALSE; - mysql_mutex_unlock(&rli->run_lock); - WSREP_DEBUG("wsrep_conflict_state now: %d", thd->wsrep_conflict_state); - WSREP_INFO("slave restart: %d", thd->wsrep_conflict_state); - thd->wsrep_conflict_state= NO_CONFLICT; - goto wsrep_restart_point; - } else { - WSREP_INFO("Slave error due to node going non-primary"); - WSREP_INFO("wsrep_restart_slave was set and therefore slave will be " - "automatically restarted when node joins back to cluster."); - wsrep_restart_slave_activated= TRUE; - } - } + { + if (wsrep_ready_get()) + { + WSREP_INFO("Slave error due to node temporarily non-primary" + "SQL slave will continue"); + wsrep_node_dropped= FALSE; + mysql_mutex_unlock(&rli->run_lock); + goto wsrep_restart_point; + } else { + WSREP_INFO("Slave error due to node going non-primary"); + WSREP_INFO("wsrep_restart_slave was set and therefore slave will be " + "automatically restarted when node joins back to cluster"); + wsrep_restart_slave_activated= TRUE; + } + } + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_EXITING); + if (WSREP(thd)) wsrep->free_connection(wsrep, thd->thread_id); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); #endif /* WITH_WSREP */ /* diff --git a/sql/sp_head.cc b/sql/sp_head.cc index c86edc47bf9..c88fe153136 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -44,6 +44,7 @@ #include "transaction.h" // trans_commit_stmt #include "sql_audit.h" #include "debug_sync.h" +#include "wsrep_trans_observer.h" /* Sufficient max length of printed destinations and frame offsets (all uints). @@ -51,7 +52,6 @@ #define SP_INSTR_UINT_MAXLEN 8 #define SP_STMT_PRINT_MAXLEN 40 - #include <my_user.h> extern "C" uchar *sp_table_key(const uchar *ptr, size_t *plen, my_bool first); @@ -1324,6 +1324,13 @@ sp_head::execute(THD *thd, bool merge_da_on_success) sql_digest_state *parent_digest= thd->m_digest; thd->m_digest= NULL; +#ifdef WITH_WSREP + if (WSREP(thd) && thd->wsrep_next_trx_id() == WSREP_UNDEFINED_TRX_ID) + { + thd->set_wsrep_next_trx_id(thd->query_id); + WSREP_DEBUG("assigned new next trx ID for SP, trx id: %lu", thd->wsrep_next_trx_id()); + } +#endif /* WITH_WSREP */ err_status= i->execute(thd, &ip); thd->m_digest= parent_digest; @@ -3566,6 +3573,24 @@ sp_instr_stmt::exec_core(THD *thd, uint *nextp) (char *)thd->security_ctx->host_or_ip, 3); int res= mysql_execute_command(thd); +#ifdef WITH_WSREP + if ((thd->is_fatal_error || thd->killed_errno()) && + (thd->wsrep_conflict_state_unsafe() == NO_CONFLICT)) + { + /* + SP was killed, and it is not due to a wsrep conflict. + We skip after_command hook at this point because + otherwise it clears the error, and cleans up the + whole transaction. For now we just return and finish + our handling once we are back to mysql_parse. + */ + WSREP_DEBUG("Skipping after_command hook for killed SP"); + } + else + { + (void) wsrep_after_command(thd, !thd->in_active_multi_stmt_transaction()); + } +#endif /* WITH_WSREP */ MYSQL_QUERY_EXEC_DONE(res); *nextp= m_ip+1; return res; @@ -4501,8 +4526,8 @@ int sp_instr_error::execute(THD *thd, uint *nextp) { DBUG_ENTER("sp_instr_error::execute"); - my_message(m_errcode, ER_THD(thd, m_errcode), MYF(0)); + WSREP_DEBUG("sp_instr_error: %s %d", ER_THD(thd, m_errcode), thd->is_error()); *nextp= m_ip+1; DBUG_RETURN(-1); } diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc index 700b4699430..fb89e0bc5b2 100644 --- a/sql/sql_alter.cc +++ b/sql/sql_alter.cc @@ -498,7 +498,7 @@ bool Sql_cmd_alter_table::execute(THD *thd) #ifdef WITH_WSREP error: - WSREP_WARN("ALTER TABLE isolation failure"); + // Jump to error may happen from WSREP_TO_ISOLATION_BEGIN DBUG_RETURN(TRUE); #endif /* WITH_WSREP */ } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e46b7675bbe..0587d401461 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -63,6 +63,9 @@ #endif #include "wsrep_mysqld.h" #include "wsrep_thd.h" +#ifdef WITH_WSREP +#include "wsrep_sr.h" +#endif bool No_such_table_error_handler::handle_condition(THD *, @@ -872,10 +875,19 @@ void close_thread_table(THD *thd, TABLE **table_ptr) The metadata lock must be released after giving back the table to the table cache. */ - DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, +#ifdef WITH_WSREP + /* if SR thread was aborted, MDL locks were released early */ + DBUG_ASSERT(thd->variables.wsrep_trx_fragment_size > 0 || + thd->mdl_context.is_lock_owner(MDL_key::TABLE, + table->s->db.str, + table->s->table_name.str, + MDL_SHARED)); +#else + DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, table->s->db.str, table->s->table_name.str, MDL_SHARED)); +#endif /* WITH_WSSREP */ table->mdl_ticket= NULL; if (table->file) @@ -3988,6 +4000,15 @@ bool open_tables(THD *thd, const DDL_options_st &options, thd->current_tablenr= 0; restart: +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd) && + (thd->wsrep_is_streaming() || + thd->variables.wsrep_trx_fragment_size > 0) && + wsrep_may_produce_SR_step(thd)) + { + wsrep_prepare_SR_for_open_tables(thd, start); + } +#endif /* WITH_WSREP */ /* Close HANDLER tables which are marked for flush or against which there are pending exclusive metadata locks. This is needed both in order to diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 0bbfdba88c7..9571c785e28 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -771,6 +771,8 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock) *scramble= '\0'; #ifdef WITH_WSREP + mysql_mutex_init(key_LOCK_wsrep_thd, &LOCK_wsrep_thd, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_wsrep_thd, &COND_wsrep_thd, NULL); wsrep_ws_handle.trx_id = WSREP_UNDEFINED_TRX_ID; wsrep_ws_handle.opaque = NULL; wsrep_retry_counter = 0; @@ -779,12 +781,20 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock) wsrep_retry_query_len = 0; wsrep_retry_command = COM_CONNECT; wsrep_consistency_check = NO_CONSISTENCY_CHECK; + wsrep_status_vars = 0; wsrep_mysql_replicated = 0; wsrep_TOI_pre_query = NULL; wsrep_TOI_pre_query_len = 0; + wsrep_fragments_sent = 0; + wsrep_trx_fragment_size = 0; + wsrep_SR_thd = false; + wsrep_rbr_buf = NULL; + wsrep_nbo_ctx = NULL; wsrep_info[sizeof(wsrep_info) - 1] = '\0'; /* make sure it is 0-terminated */ wsrep_sync_wait_gtid = WSREP_GTID_UNDEFINED; wsrep_affected_rows = 0; + wsrep_has_ignored_error = false; + m_wsrep_next_trx_id = WSREP_UNDEFINED_TRX_ID; wsrep_replicate_GTID = false; wsrep_skip_wsrep_GTID = false; #endif @@ -1221,10 +1231,14 @@ void THD::init(bool skip_lock) first_successful_insert_id_in_cur_stmt= 0; #ifdef WITH_WSREP wsrep_exec_mode= wsrep_applier ? REPL_RECV : LOCAL_STATE; - wsrep_conflict_state= NO_CONFLICT; - wsrep_query_state= QUERY_IDLE; + m_wsrep_conflict_state= NO_CONFLICT; + m_wsrep_query_state= QUERY_IDLE; wsrep_last_query_id= 0; + wsrep_xid.null(); + wsrep_skip_locking= FALSE; wsrep_trx_meta.gtid= WSREP_GTID_UNDEFINED; + wsrep_node_uuid(wsrep_trx_meta.stid.node); + wsrep_trx_meta.stid.trx= WSREP_UNDEFINED_TRX_ID; wsrep_trx_meta.depends_on= WSREP_SEQNO_UNDEFINED; wsrep_converted_lock_session= false; wsrep_retry_counter= 0; @@ -1234,8 +1248,16 @@ void THD::init(bool skip_lock) wsrep_mysql_replicated = 0; wsrep_TOI_pre_query = NULL; wsrep_TOI_pre_query_len = 0; + wsrep_fragments_sent = 0; + wsrep_trx_fragment_size = 0; + wsrep_SR_thd = false; + wsrep_rbr_buf = NULL; + wsrep_nbo_ctx = NULL; wsrep_sync_wait_gtid = WSREP_GTID_UNDEFINED; + wsrep_last_written_gtid = WSREP_GTID_UNDEFINED; + wsrep_SR_rollback_replicated_for_trx = WSREP_UNDEFINED_TRX_ID; wsrep_affected_rows = 0; + m_wsrep_next_trx_id = WSREP_UNDEFINED_TRX_ID; wsrep_replicate_GTID = false; wsrep_skip_wsrep_GTID = false; #endif /* WITH_WSREP */ @@ -1454,6 +1476,70 @@ void THD::cleanup(void) DBUG_ENTER("THD::cleanup"); DBUG_ASSERT(cleanup_done == 0); +#ifdef WITH_WSREP + if (this->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID) + { + WSREP_LOG_THD(this, "THD::cleanup"); + } + /* + Before cleanup make sure that all wsrep transactions + will be rolled back. + */ + if (WSREP_CLIENT_NNULL(this)) + { + mysql_mutex_lock(&this->LOCK_wsrep_thd); + DBUG_ASSERT(this->wsrep_query_state() == QUERY_EXITING); + /* + Background rollback is in process + */ + if (this->wsrep_is_rolling_back()) + { + /* + Rollback thread is rolling back a transaction for this thd, + wait until it has finished. + */ + while (this->wsrep_is_rolling_back()) + { + mysql_mutex_unlock(&this->LOCK_wsrep_thd); + my_sleep(1000); + mysql_mutex_lock(&this->LOCK_wsrep_thd); + } + DBUG_ASSERT(this->wsrep_conflict_state() == ABORTED); + } + + /* + BF abort happened while the client was idle. + */ + if (this->wsrep_conflict_state() == ABORTED) + { + wsrep_cleanup_transaction(this); + } + + if (this->wsrep_conflict_state() == MUST_ABORT) + { + wsrep_client_rollback(this); + } + + mysql_mutex_unlock(&this->LOCK_wsrep_thd); + + trans_rollback(this); + mysql_mutex_lock(&this->LOCK_wsrep_thd); + + if (this->wsrep_exec_mode == LOCAL_ROLLBACK || + this->wsrep_conflict_state() == ABORTING) + { + wsrep_post_rollback(this); + wsrep_cleanup_transaction(this); + } + + DBUG_ASSERT(this->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID && + this->wsrep_conflict_state() == NO_CONFLICT); + + mysql_mutex_unlock(&this->LOCK_wsrep_thd); + } + + this->wsrep_client_thread= 0; +#endif /* WITH_WSREP */ set_killed(KILL_CONNECTION); #ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE if (transaction.xid_state.xa_state == XA_PREPARED) @@ -1603,15 +1689,25 @@ THD::~THD() THD is not deleted while they access it. The following mutex_lock ensures that no one else is using this THD and it's now safe to delete */ + if (WSREP(this)) mysql_mutex_lock(&LOCK_wsrep_thd); mysql_mutex_lock(&LOCK_thd_kill); mysql_mutex_unlock(&LOCK_thd_kill); + if (WSREP(this)) mysql_mutex_unlock(&LOCK_wsrep_thd); -#ifdef WITH_WSREP - delete wsrep_rgi; -#endif if (!free_connection_done) free_connection(); +#ifdef WITH_WSREP + mysql_mutex_lock(&LOCK_wsrep_thd); + mysql_mutex_unlock(&LOCK_wsrep_thd); + mysql_mutex_destroy(&LOCK_wsrep_thd); + mysql_cond_destroy(&COND_wsrep_thd); + if (wsrep_rgi != NULL) { + delete wsrep_rgi; + wsrep_rgi = NULL; + } + if (wsrep_status_vars) wsrep->stats_free(wsrep, wsrep_status_vars); +#endif mdl_context.destroy(); free_root(&transaction.mem_root,MYF(0)); @@ -1793,6 +1889,7 @@ void THD::awake_no_mutex(killed_state state_to_set) DBUG_PRINT("enter", ("this: %p current_thd: %p state: %d", this, current_thd, (int) state_to_set)); THD_CHECK_SENTRY(this); + if (WSREP(this)) mysql_mutex_assert_owner(&LOCK_wsrep_thd); mysql_mutex_assert_owner(&LOCK_thd_kill); print_aborted_warning(3, "KILLED"); @@ -1977,14 +2074,21 @@ bool THD::notify_shared_lock(MDL_context_owner *ctx_in_use, */ if (!thd_table->needs_reopen()) { +#ifdef WITH_WSREP signalled|= mysql_lock_abort_for_thread(this, thd_table); - if (WSREP(this) && wsrep_thd_is_BF(this, FALSE)) + if (WSREP_NNULL(this) && wsrep_thd_is_BF((void*)this, FALSE)) { WSREP_DEBUG("remove_table_from_cache: %llu", (unsigned long long) this->real_id); wsrep_abort_thd((void *)this, (void *)in_use, FALSE); } } + else + { +#else + signalled|= mysql_lock_abort_for_thread(this, thd_table); +#endif /* WITH_WSREP */ + } } } mysql_mutex_unlock(&in_use->LOCK_thd_data); @@ -4968,11 +5072,13 @@ extern "C" int thd_non_transactional_update(const MYSQL_THD thd) extern "C" int thd_binlog_format(const MYSQL_THD thd) { +#ifdef WITH_WSREP if (WSREP(thd)) { /* for wsrep binlog format is meaningful also when binlogging is off */ - return (int) thd->wsrep_binlog_format(); + return (int) WSREP_BINLOG_FORMAT(thd->variables.binlog_format); } +#endif /* WITH_WSREP */ if (mysql_bin_log.is_open() && (thd->variables.option_bits & OPTION_BIN_LOG)) return (int) thd->variables.binlog_format; return BINLOG_FORMAT_UNSPEC; @@ -5455,6 +5561,13 @@ void THD::set_query_and_id(char *query_arg, uint32 query_length_arg, set_query_inner(query_arg, query_length_arg, cs); mysql_mutex_unlock(&LOCK_thd_data); query_id= new_query_id; +#ifdef WITH_WSREP + if (WSREP_NNULL(this) && wsrep_next_trx_id() == WSREP_UNDEFINED_TRX_ID) + { + set_wsrep_next_trx_id(query_id); + WSREP_DEBUG("assigned new next trx id: %lu", wsrep_next_trx_id()); + } +#endif /* WITH_WSREP */ } /** Assign a new value to thd->mysys_var. */ @@ -5900,9 +6013,27 @@ int THD::decide_logging_format(TABLE_LIST *tables) binlogging is off, or if the statement is filtered out from the binlog by filtering rules. */ +#ifdef WITH_WSREP + if (WSREP_CLIENT_NNULL(this) && variables.wsrep_trx_fragment_size > 0) + { + if (!is_current_stmt_binlog_format_row()) + { + my_message(ER_NOT_SUPPORTED_YET, + "Streaming replication not supported with " + "binlog_format=STATEMENT", MYF(0)); + DBUG_RETURN(-1); + } + } + + if ((WSREP_EMULATE_BINLOG_NNULL(this) || + (mysql_bin_log.is_open() && (variables.option_bits & OPTION_BIN_LOG))) && + !(wsrep_binlog_format() == BINLOG_FORMAT_STMT && + !binlog_filter->db_ok(db.str))) +#else if (mysql_bin_log.is_open() && (variables.option_bits & OPTION_BIN_LOG) && !(wsrep_binlog_format() == BINLOG_FORMAT_STMT && !binlog_filter->db_ok(db.str))) +#endif /* WITH_WSREP */ { if (is_bulk_op()) diff --git a/sql/sql_class.h b/sql/sql_class.h index 25e2d736cdc..8e08864abf7 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -61,8 +61,27 @@ void set_thd_stage_info(void *thd, #include "my_apc.h" #include "rpl_gtid.h" -#include "wsrep_mysqld.h" +#ifdef WITH_WSREP +#include <vector> +#include "wsrep_mysqld.h" +#include "wsrep_binlog.h" +struct wsrep_thd_shadow { + ulonglong options; + uint server_status; + enum wsrep_exec_mode wsrep_exec_mode; + Vio *vio; + ulong tx_isolation; + char *db; + size_t db_length; + my_hrtime_t user_time; + longlong row_count_func; +}; +#include <map> +#include <set> +#include <string> +typedef std::map<std::string, std::set<std::string> > wsrep_key_set; +#endif /* WITH_WSREP */ class Reprepare_observer; class Relay_log_info; struct rpl_group_info; @@ -705,10 +724,12 @@ typedef struct system_variables my_bool wsrep_on; my_bool wsrep_causal_reads; + uint wsrep_sync_wait; + ulong wsrep_retry_autocommit; + ulong wsrep_trx_fragment_size; + ulong wsrep_trx_fragment_unit; + ulong wsrep_OSU_method; my_bool wsrep_dirty_reads; - uint wsrep_sync_wait; - ulong wsrep_retry_autocommit; - ulong wsrep_OSU_method; double long_query_time_double, max_statement_time_double; my_bool pseudo_slave_mode; @@ -3204,7 +3225,6 @@ public: mysql_bin_log.start_union_events() call. */ bool unioned_events_trans; - /* 'queries' (actually SP statements) that run under inside this binlog union have thd->query_id >= first_query_id. @@ -3212,7 +3232,9 @@ public: query_id_t first_query_id; } binlog_evt_union; + mysql_mutex_t LOCK_wsrep_thd; mysql_cond_t COND_wsrep_thd; + /** Internal parser state. Note that since the parser is not re-entrant, we keep only one parser @@ -3295,11 +3317,17 @@ public: void awake_no_mutex(killed_state state_to_set); void awake(killed_state state_to_set) { + /* + mutex locking order (LOCK_wsrep_thd - LOCK_thd_kill)) requires + to grab LOCK_wsrep_thd here + */ + mysql_mutex_lock(&LOCK_wsrep_thd); mysql_mutex_lock(&LOCK_thd_kill); awake_no_mutex(state_to_set); mysql_mutex_unlock(&LOCK_thd_kill); + mysql_mutex_unlock(&LOCK_wsrep_thd); } - + /** Disconnect the associated communication endpoint. */ void disconnect(); @@ -4477,6 +4505,13 @@ public: void set_query_id(query_id_t new_query_id) { query_id= new_query_id; +#ifdef WITH_WSREP + if (WSREP(this) && wsrep_next_trx_id() == WSREP_UNDEFINED_TRX_ID) + { + set_wsrep_next_trx_id(query_id); + WSREP_DEBUG("assigned new next trx id: %lu", wsrep_next_trx_id()); + } +#endif /* WITH_WSREP */ } void set_open_tables(TABLE *open_tables_arg) { @@ -4738,33 +4773,248 @@ public: const bool wsrep_applier; /* dedicated slave applier thread */ bool wsrep_applier_closing; /* applier marked to close */ bool wsrep_client_thread; /* to identify client threads*/ - bool wsrep_PA_safe; - bool wsrep_converted_lock_session; - bool wsrep_apply_toi; /* applier processing in TOI */ enum wsrep_exec_mode wsrep_exec_mode; query_id_t wsrep_last_query_id; - enum wsrep_query_state wsrep_query_state; - enum wsrep_conflict_state wsrep_conflict_state; + XID wsrep_xid; + + /** This flag denotes that record locking should be skipped during INSERT + and gap locking during SELECT. Only used by the streaming replication thread + that only modifies the wsrep_schema.SR table. */ + my_bool wsrep_skip_locking; + + /* + Delegated rollback: + + Wsrep_query_state, wsrep_conflict_state and wsrep_exec_mode define + together the state for rollback process. In most of the cases the + client thread will handle the rollback, but if the BF abort happens when + the client thread is in QUERY_IDLE state, the rollback process + is delegated to rollbacker thread. In this case rollbacker thread + will do the rollback on behalf of client thread and will leave + the states into the following + * wsrep_query_state = QUERY_IDLE + * wsrep_conflict_state = ABORTED + * wsrep_exec_mode = LOCAL_ROLLBACK + */ + + /* + Set wsrep_query_state + + Asserts LOCK_wsrep_thd ownership. + */ + void set_wsrep_query_state(enum wsrep_query_state state) + { + mysql_mutex_assert_owner(&LOCK_wsrep_thd); + /* + State machine: + + QI - QUERY_IDLE + QX - QUERY_EXEC + QC - QUERY_COMMITTING + QOC - QUERY_ORDERED_COMMIT + QE - QUERY_EXITING + + |---> QE + | + o--> QI <-> QX -> QC -> QOC + ^ | | + |------------- + */ + static const bool allowed[QUERY_EXITING + 1][QUERY_EXITING + 1] = + { + /* QI QX QC QOC, QE To / From */ + { false, true, false, false, true }, /* QI */ + { true , false, true, false, false }, /* QX */ + { false, true, false, true, false }, /* QC */ + { false, true, false, false, false }, /* QOC */ + { false, false, false, false, false } /* QE */ + }; + if (allowed[m_wsrep_query_state][state] == false) + { + WSREP_DEBUG("Unallowed query state change %d -> %d", + m_wsrep_query_state, state); + } + DBUG_ASSERT(allowed[m_wsrep_query_state][state] == true); + m_wsrep_query_state= state; + } + + /* + Return current wsrep_query_state + + Asserts LOCK_wsrep_thd ownership + */ + enum wsrep_query_state wsrep_query_state() const + { + mysql_mutex_assert_owner(&LOCK_wsrep_thd); + return m_wsrep_query_state; + } + + /* + Return current wsrep_query_state + + Does not assert LOCK_wsrep_thd ownership, useful for + debugging and logging where strict access is not + absolutely required. + */ + enum wsrep_query_state wsrep_query_state_unsafe() const + { + return m_wsrep_query_state; + } + + void set_wsrep_conflict_state(enum wsrep_conflict_state state) + { + mysql_mutex_assert_owner(&LOCK_wsrep_thd); + /* + State machine + + NC - NO_CONFLICT + MA - MUST_ABORT + AB - ABORTING + AD - ABORTED + MR - MUST_REPLAY + RI - REPLAYING + RA - RETRY_AUTOCOMMIT + CF - CERT_FAILURE + + 1) BF abort + 2) Cert failure or rollback + 3) Pre commit returns success, so the transaction must be replayed + 4) Pre commit return certification failure, cleanup after certification + failure + 5) Post rollback phase + 6) Is autocommit and wsrep_retry_autocommit is set + 7) Simultaneous certification failure and BF abort + + 4 5 + -> NC <-----------------> CF ------------------- + | ^^ | 7 | + | || 1 2 | | + | 6||-----------> MA --------> AB ------> AD <-| + | | | ^ | + | |-> RA | 3 | | + | | | | + | -> MR -> RI - | + | | | + |------------------------------------------ + + */ + + static const bool allowed[CERT_FAILURE + 1][CERT_FAILURE + 1] = + { + /* NC MA AB AD MR RI RA CF To / From */ + { false, true, false, false, false, false, true, true }, /* NC */ + { true, false, true, false, true, false, false, false }, /* MA */ + { false, false, false, true, false, false, false, false }, /* AB */ + { true , false, false, false, false, false, false, false }, /* AD */ + { false, false, false, false, false, true, false, false }, /* MR */ + { true, false, true, false, false, false, false, false }, /* RI */ + { true, false, false, false, false, false, false, false }, /* RA */ + { true, false, true, true, false, false, false, false } /* CF */ + }; + if (allowed[m_wsrep_conflict_state][state] == false) + { + WSREP_DEBUG("Unallowed conflict state change %d -> %d", + m_wsrep_conflict_state, state); + } + DBUG_ASSERT(allowed[m_wsrep_conflict_state][state] == true); + + /* + Sanity checks agains query state and thread context + */ + switch (state) + { + case MUST_ABORT: + break; + default: + /* + Only the current thread context may change the state apart from + NC -> MA transition. + */ + DBUG_ASSERT(this == current_thd); + break; + } +#ifndef DBUG_OFF + if (state == NO_CONFLICT) + { + m_wsrep_conflict_state_history.clear(); + } + else + { + m_wsrep_conflict_state_history.push_back(m_wsrep_conflict_state); + } +#endif /* DBUG_OFF */ + m_wsrep_conflict_state= state; + } + + /* + Return wsrep_conflict_state + + Asserts LOCK_wsrep_thd ownership + */ + enum wsrep_conflict_state wsrep_conflict_state() const + { + mysql_mutex_assert_owner(&LOCK_wsrep_thd); + return m_wsrep_conflict_state; + } + + /* + Return wsrep_conflict_state + + Does not assert LOCK_wsrep_thd ownership, useful mostly + for debugging and logging where strict access is not + aboslutely required. + */ + enum wsrep_conflict_state wsrep_conflict_state_unsafe() const + { + return m_wsrep_conflict_state; + } + + /* + Check if wsrep rollback process has started + */ + bool wsrep_is_rolling_back() const + { + return (wsrep_conflict_state() == MUST_ABORT || + wsrep_conflict_state() == ABORTING); + } + +private: + enum wsrep_query_state m_wsrep_query_state; + enum wsrep_conflict_state m_wsrep_conflict_state; +#ifndef DBUG_OFF + std::vector<enum wsrep_conflict_state> m_wsrep_conflict_state_history; +#endif /* DBUG_OFF */ +public: + + // changed from wsrep_seqno_t to wsrep_trx_meta_t in wsrep API rev 75 + // wsrep_seqno_t wsrep_trx_seqno; wsrep_trx_meta_t wsrep_trx_meta; uint32 wsrep_rand; Relay_log_info *wsrep_rli; rpl_group_info *wsrep_rgi; + bool wsrep_converted_lock_session; wsrep_ws_handle_t wsrep_ws_handle; +#ifdef WSREP_PROC_INFO + // char wsrep_info[128]; /* string for dynamic proc info */ +#endif /* WSREP_PROC_INFO */ ulong wsrep_retry_counter; // of autocommit - char *wsrep_retry_query; + bool wsrep_PA_safe; + char* wsrep_retry_query; size_t wsrep_retry_query_len; enum enum_server_command wsrep_retry_command; - enum wsrep_consistency_check_mode + enum wsrep_consistency_check_mode wsrep_consistency_check; + wsrep_stats_var* wsrep_status_vars; int wsrep_mysql_replicated; - const char *wsrep_TOI_pre_query; /* a query to apply before - the actual TOI query */ + const char* wsrep_TOI_pre_query; /* a query to apply before + the actual TOI query */ size_t wsrep_TOI_pre_query_len; wsrep_po_handle_t wsrep_po_handle; size_t wsrep_po_cnt; #ifdef GTID_SUPPORT + my_bool wsrep_po_in_trans; rpl_sid wsrep_po_sid; -#endif /* GTID_SUPPORT */ +#endif /* GTID_SUPPORT */ void *wsrep_apply_format; char wsrep_info[128]; /* string for dynamic proc info */ /* @@ -4773,10 +5023,90 @@ public: table updates from being replicated to other nodes via galera replication. */ bool wsrep_ignore_table; + bool wsrep_apply_toi; /* applier processing in TOI */ + ulong wsrep_fragments_sent; // # of fragments replicated + // for trx + bool wsrep_SR_thd; // is applier THD for streaming + // transaction + wsrep_trx_id_t wsrep_SR_rollback_replicated_for_trx; + wsrep_fragment_set wsrep_SR_fragments; + wsrep_key_set wsrep_SR_keys; + TABLE_LIST wsrep_SR_table; + uchar* wsrep_rbr_buf; + Wsrep_nbo_ctx* wsrep_nbo_ctx; // Context for non-blocking operations wsrep_gtid_t wsrep_sync_wait_gtid; + wsrep_gtid_t wsrep_last_written_gtid; ulong wsrep_affected_rows; + bool wsrep_has_ignored_error; bool wsrep_replicate_GTID; bool wsrep_skip_wsrep_GTID; + + bool wsrep_is_streaming() + { + return ((wsrep_fragments_sent > 0) && + (wsrep_exec_mode == LOCAL_STATE || + wsrep_exec_mode == LOCAL_COMMIT || + wsrep_exec_mode == LOCAL_ROLLBACK)); + } + + /* + Return true if the current transaction has been assigned a valid sequence + number. + */ + bool wsrep_trx_has_seqno() const + { + DBUG_ASSERT(wsrep_trx_meta.gtid.seqno == WSREP_SEQNO_UNDEFINED || + wsrep_trx_meta.gtid.seqno > 0); + return (wsrep_trx_meta.gtid.seqno > 0); + } + + /* + Return true if current transaction must go through commit ordering. + This is the case if the transaction has been assigned valid seqno + and has been assigned write set handle. + */ + bool wsrep_trx_must_order_commit() const + { + return (wsrep_ws_handle.opaque && wsrep_trx_has_seqno()); + } + + /* + Transaction id: + * m_wsrep_next_trx_id is assigned on the first query after + wsrep_next_trx_id() return WSREP_UNDEFINED_TRX_ID + * Each storage engine must assign value of wsrep_next_trx_id() + via wsrep_ws_handle_for_trx() when the transaction starts. + * Effective transaction id is returned via wsrep_trx_id() + */ + + /* + Return effective transaction id + */ + wsrep_trx_id_t wsrep_trx_id() const + { + return wsrep_ws_handle.trx_id; + } + + /* + Set next trx id + */ + void set_wsrep_next_trx_id(query_id_t query_id) + { + DBUG_ASSERT(wsrep_ws_handle.trx_id == WSREP_UNDEFINED_TRX_ID); + //DBUG_ASSERT(query_id != 0); + m_wsrep_next_trx_id = (wsrep_trx_id_t) query_id; + } + /* + Return next trx id + */ + wsrep_trx_id_t wsrep_next_trx_id() const + { + return m_wsrep_next_trx_id; + } + +private: + wsrep_trx_id_t m_wsrep_next_trx_id; /* cast from query_id_t */ +public: #endif /* WITH_WSREP */ /* Handling of timeouts for commands */ @@ -6255,7 +6585,7 @@ public: be rolled back or that do not expect any previously metadata locked tables. */ -#define CF_IMPLICT_COMMIT_BEGIN (1U << 6) +#define CF_IMPLICIT_COMMIT_BEGIN (1U << 6) /** Implicitly commit after the SQL statement. @@ -6273,7 +6603,7 @@ public: before and after every DDL statement and any statement that modifies our currently non-transactional system tables. */ -#define CF_AUTO_COMMIT_TRANS (CF_IMPLICT_COMMIT_BEGIN | CF_IMPLICIT_COMMIT_END) +#define CF_AUTO_COMMIT_TRANS (CF_IMPLICIT_COMMIT_BEGIN | CF_IMPLICIT_COMMIT_END) /** Diagnostic statement. @@ -6317,6 +6647,13 @@ public: */ #define CF_DISALLOW_IN_RO_TRANS (1U << 15) +#ifdef WITH_WSREP +/** + DDL statement that may be subject to error filtering. +*/ +#define CF_WSREP_MAY_IGNORE_ERRORS (1U << 24) +#endif /* WITH_WSREP */ + /** Statement that need the binlog format to be unchanged. */ diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index b48070b9c8f..088dec72313 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -1186,8 +1186,7 @@ void end_connection(THD *thd) (longlong) thd->thread_id, rcode); } } - thd->wsrep_client_thread= 0; -#endif +#endif /* WITH_WSREP */ plugin_thdvar_cleanup(thd); if (thd->user_connect) @@ -1408,7 +1407,7 @@ void do_handle_one_connection(CONNECT *connect) if (WSREP(thd)) { mysql_mutex_lock(&thd->LOCK_thd_data); - thd->wsrep_query_state= QUERY_EXITING; + thd->set_wsrep_query_state(QUERY_EXITING); mysql_mutex_unlock(&thd->LOCK_thd_data); } #endif diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 51acf10a98a..a6aa8b999dc 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -3902,10 +3902,14 @@ bool select_insert::prepare_eof() DBUG_PRINT("enter", ("trans_table=%d, table_type='%s'", trans_table, table->file->table_type())); - error= (IF_WSREP((thd->wsrep_conflict_state == MUST_ABORT || - thd->wsrep_conflict_state == CERT_FAILURE) ? -1 :, ) - (thd->locked_tables_mode <= LTM_LOCK_TABLES ? - table->file->ha_end_bulk_insert() : 0)); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + + error= (IF_WSREP((thd->wsrep_conflict_state() == MUST_ABORT || + thd->wsrep_conflict_state() == CERT_FAILURE) ? -1 :, ) + (thd->locked_tables_mode <= LTM_LOCK_TABLES ? + table->file->ha_end_bulk_insert() : 0)); + + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); if (likely(!error) && unlikely(thd->is_error())) error= thd->get_stmt_da()->sql_errno(); @@ -4566,8 +4570,17 @@ bool select_create::send_eof() #ifdef WITH_WSREP if (WSREP_ON) { + if (thd->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID) + { + (void) wsrep_ws_handle_for_trx(&thd->wsrep_ws_handle, + thd->wsrep_next_trx_id()); + } + DBUG_ASSERT(thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID); + WSREP_DEBUG("CTAS key append for trx: %lu thd %llu query %lld ", + thd->wsrep_trx_id(), thd->thread_id, thd->query_id); + /* - append table level exclusive key for CTAS + append table level exclusive key for CTAS */ wsrep_key_arr_t key_arr= {0, 0}; wsrep_prepare_keys_for_isolation(thd, @@ -4575,15 +4588,15 @@ bool select_create::send_eof() create_table->table_name.str, table_list, &key_arr); - int rcode = wsrep->append_key( - wsrep, - &thd->wsrep_ws_handle, - key_arr.keys, //&wkey, - key_arr.keys_len, - WSREP_KEY_EXCLUSIVE, - false); + int rcode = wsrep->append_key(wsrep, + &thd->wsrep_ws_handle, + key_arr.keys, //&wkey, + key_arr.keys_len, + WSREP_KEY_EXCLUSIVE, + false); wsrep_keys_free(&key_arr); - if (rcode) { + if (rcode) + { DBUG_PRINT("wsrep", ("row key failed: %d", rcode)); WSREP_ERROR("Appending table key for CTAS failed: %s, %d", (wsrep_thd_query(thd)) ? @@ -4591,7 +4604,7 @@ bool select_create::send_eof() return true; } /* If commit fails, we should be able to reset the OK status. */ - thd->get_stmt_da()->set_overwrite_status(TRUE); + thd->get_stmt_da()->set_overwrite_status(true); } #endif /* WITH_WSREP */ trans_commit_stmt(thd); @@ -4600,13 +4613,13 @@ bool select_create::send_eof() #ifdef WITH_WSREP if (WSREP_ON) { - thd->get_stmt_da()->set_overwrite_status(FALSE); - mysql_mutex_lock(&thd->LOCK_thd_data); - if (thd->wsrep_conflict_state != NO_CONFLICT) + thd->get_stmt_da()->set_overwrite_status(false); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state() != NO_CONFLICT) { - WSREP_DEBUG("select_create commit failed, thd: %lld err: %d %s", - (longlong) thd->thread_id, thd->wsrep_conflict_state, - thd->query()); + WSREP_DEBUG("select_create commit failed, thd: %lld err: %d %s", + thd->thread_id, thd->wsrep_conflict_state(), + WSREP_QUERY(thd)); mysql_mutex_unlock(&thd->LOCK_thd_data); abort_result_set(); DBUG_RETURN(true); diff --git a/sql/sql_load.cc b/sql/sql_load.cc index dd6e723c953..c2d4de0e081 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -42,6 +42,8 @@ #include "sql_derived.h" #include "sql_show.h" +#include "wsrep_mysqld.h" + extern "C" int _my_b_net_read(IO_CACHE *info, uchar *Buffer, size_t Count); class XML_TAG { @@ -106,7 +108,7 @@ static bool wsrep_load_data_split(THD *thd, const TABLE *table, { DBUG_ENTER("wsrep_load_data_split"); - if (!wsrep_load_data_splitting || !wsrep_on(thd) + if (!wsrep_load_data_splitting || !WSREP(thd) || !info.records || (info.records % 10000) || !thd->transaction.stmt.ha_list || thd->transaction.stmt.ha_list->ht() != binlog_hton @@ -119,10 +121,15 @@ static bool wsrep_load_data_split(THD *thd, const TABLE *table, if (hton->db_type != DB_TYPE_INNODB) DBUG_RETURN(false); WSREP_DEBUG("intermediate transaction commit in LOAD DATA"); +#ifdef OUT /* this is old mariadb implementation... */ if (wsrep_run_wsrep_commit(thd, true) != WSREP_TRX_OK) DBUG_RETURN(true); if (binlog_hton->commit(binlog_hton, thd, true)) DBUG_RETURN(true); wsrep_post_commit(thd, true); hton->commit(hton, thd, true); +#else + /* ...which is replaced by this */ + wsrep_tc_log_commit(thd); +#endif table->file->extra(HA_EXTRA_FAKE_START_STMT); } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1baa26ab465..18cded52a74 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -111,8 +111,9 @@ #include "wsrep_mysqld.h" #include "wsrep_thd.h" +#include "wsrep_trans_observer.h" /* wsrep transaction hooks */ -static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, +static bool wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, Parser_state *parser_state, bool is_com_multi, bool is_next_command); @@ -877,6 +878,16 @@ void init_update_queries(void) sql_command_flags[SQLCOM_REVOKE_ALL]|= CF_DISALLOW_IN_RO_TRANS; sql_command_flags[SQLCOM_INSTALL_PLUGIN]|= CF_DISALLOW_IN_RO_TRANS; sql_command_flags[SQLCOM_UNINSTALL_PLUGIN]|= CF_DISALLOW_IN_RO_TRANS; +#ifdef WITH_WSREP + /* + Statements for which some errors are ignored when + wsrep_ignore_apply_errors = WSREP_IGNORE_ERRORS_ON_RECONCILING_DDL + */ + sql_command_flags[SQLCOM_DROP_DB]|= CF_WSREP_MAY_IGNORE_ERRORS; + sql_command_flags[SQLCOM_DROP_TABLE]|= CF_WSREP_MAY_IGNORE_ERRORS; + sql_command_flags[SQLCOM_DROP_INDEX]|= CF_WSREP_MAY_IGNORE_ERRORS; + sql_command_flags[SQLCOM_ALTER_TABLE]|= CF_WSREP_MAY_IGNORE_ERRORS; +#endif /* WITH_WSREP */ } bool sqlcom_can_generate_row_events(const THD *thd) @@ -1174,6 +1185,7 @@ static enum enum_server_command fetch_command(THD *thd, char *packet) #ifdef WITH_WSREP static bool wsrep_tables_accessible_when_detached(const TABLE_LIST *tables) { + bool accessible_tables = true; for (const TABLE_LIST *table= tables; table; table= table->next_global) { TABLE_CATEGORY c; @@ -1182,7 +1194,7 @@ static bool wsrep_tables_accessible_when_detached(const TABLE_LIST *tables) if (c != TABLE_CATEGORY_INFORMATION && c != TABLE_CATEGORY_PERFORMANCE) return false; } - return true; + return accessible_tables; } #endif /* WITH_WSREP */ #ifndef EMBEDDED_LIBRARY @@ -1212,19 +1224,6 @@ bool do_command(THD *thd) enum enum_server_command command; DBUG_ENTER("do_command"); -#ifdef WITH_WSREP - if (WSREP(thd)) - { - mysql_mutex_lock(&thd->LOCK_thd_data); - thd->wsrep_query_state= QUERY_IDLE; - if (thd->wsrep_conflict_state==MUST_ABORT) - { - wsrep_client_rollback(thd); - } - mysql_mutex_unlock(&thd->LOCK_thd_data); - } -#endif /* WITH_WSREP */ - /* indicator of uninitialized lex => normal flow of errors handling (see my_message_sql) @@ -1265,29 +1264,6 @@ bool do_command(THD *thd) DEBUG_SYNC(thd, "before_do_command_net_read"); packet_length= my_net_read_packet(net, 1); -#ifdef WITH_WSREP - if (WSREP(thd)) { - mysql_mutex_lock(&thd->LOCK_thd_data); - - /* these THD's are aborted or are aborting during being idle */ - if (thd->wsrep_conflict_state == ABORTING) - { - while (thd->wsrep_conflict_state == ABORTING) { - mysql_mutex_unlock(&thd->LOCK_thd_data); - my_sleep(1000); - mysql_mutex_lock(&thd->LOCK_thd_data); - } - thd->store_globals(); - } - else if (thd->wsrep_conflict_state == ABORTED) - { - thd->store_globals(); - } - - thd->wsrep_query_state= QUERY_EXEC; - mysql_mutex_unlock(&thd->LOCK_thd_data); - } -#endif /* WITH_WSREP */ if (unlikely(packet_length == packet_error)) { @@ -1295,20 +1271,6 @@ bool do_command(THD *thd) net->error, vio_description(net->vio))); -#ifdef WITH_WSREP - if (WSREP(thd)) - { - mysql_mutex_lock(&thd->LOCK_thd_data); - if (thd->wsrep_conflict_state == MUST_ABORT) - { - DBUG_PRINT("wsrep",("aborted for wsrep rollback: %lu", - (ulong) thd->real_id)); - wsrep_client_rollback(thd); - } - mysql_mutex_unlock(&thd->LOCK_thd_data); - } -#endif /* WITH_WSREP */ - /* Instrument this broken statement as "statement/com/error" */ thd->m_statement_psi= MYSQL_REFINE_STATEMENT(thd->m_statement_psi, com_statement_info[COM_END]. @@ -1365,7 +1327,7 @@ bool do_command(THD *thd) Bail out if DB snapshot has not been installed. */ if (!thd->wsrep_applier && - (!wsrep_ready || wsrep_reject_queries != WSREP_REJECT_NONE) && + (!wsrep_ready_get() || wsrep_reject_queries != WSREP_REJECT_NONE) && (server_command_flags[command] & CF_SKIP_WSREP_CHECK) == 0) { my_message(ER_UNKNOWN_COM_ERROR, @@ -1381,7 +1343,7 @@ bool do_command(THD *thd) goto out; } } -#endif +#endif /* WITH_WSREP */ /* Restore read timeout value */ my_net_set_read_timeout(net, thd->variables.net_read_timeout); @@ -1390,37 +1352,6 @@ bool do_command(THD *thd) DBUG_ASSERT(!thd->apc_target.is_enabled()); return_value= dispatch_command(command, thd, packet+1, (uint) (packet_length-1), FALSE, FALSE); -#ifdef WITH_WSREP - if (WSREP(thd)) - { - while (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT) - { - WSREP_DEBUG("Retry autocommit for: %s\n", thd->wsrep_retry_query); - CHARSET_INFO *current_charset = thd->variables.character_set_client; - if (!is_supported_parser_charset(current_charset)) - { - /* Do not use non-supported parser character sets */ - WSREP_WARN("Current client character set is non-supported parser " - "character set: %s", current_charset->csname); - thd->variables.character_set_client = &my_charset_latin1; - WSREP_WARN("For retry temporally setting character set to : %s", - my_charset_latin1.csname); - } - thd->clear_error(); - return_value= dispatch_command(command, thd, thd->wsrep_retry_query, - thd->wsrep_retry_query_len, FALSE, FALSE); - thd->variables.character_set_client = current_charset; - } - - if (thd->wsrep_retry_query && thd->wsrep_conflict_state != REPLAYING) - { - my_free(thd->wsrep_retry_query); - thd->wsrep_retry_query = NULL; - thd->wsrep_retry_query_len = 0; - thd->wsrep_retry_command = COM_CONNECT; - } - } -#endif /* WITH_WSREP */ DBUG_ASSERT(!thd->apc_target.is_enabled()); out: @@ -1576,36 +1507,75 @@ bool dispatch_command(enum enum_server_command command, THD *thd, compile_time_assert(COM_END == 255); #ifdef WITH_WSREP - if (WSREP(thd)) + bool wsrep_on= WSREP_ON; + if (wsrep_on) { - if (!thd->in_multi_stmt_transaction_mode()) + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + DBUG_ASSERT(thd->wsrep_query_state() == QUERY_IDLE); + if (thd->wsrep_is_rolling_back()) { - thd->wsrep_PA_safe= true; + /* + Rollback thread is rolling back a transaction for this thd, + wait until it has finished. + */ + while (thd->wsrep_is_rolling_back()) + { + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + my_sleep(1000); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + } + DBUG_ASSERT(thd->wsrep_conflict_state() == ABORTED); } - mysql_mutex_lock(&thd->LOCK_thd_data); - thd->wsrep_query_state= QUERY_EXEC; - if (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT) - { - thd->wsrep_conflict_state= NO_CONFLICT; - } - if (thd->wsrep_conflict_state== MUST_ABORT) - { - wsrep_client_rollback(thd); - } - /* We let COM_QUIT and COM_STMT_CLOSE to execute even if wsrep aborted. */ - if (thd->wsrep_conflict_state == ABORTED && - command != COM_STMT_CLOSE && command != COM_QUIT) + /* + BF aborter should atomically check thd query state and start + background rollback process if the thd query state is QUERY_IDLE. + Because the wait for the background rollback is done above we should + be here either in NO_CONFLICT or in ABORTED state. + */ + DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT || + thd->wsrep_conflict_state() == ABORTED); + + thd->set_wsrep_query_state(QUERY_EXEC); + + /* + Aborted by background rollbacker thread. Jump straight to dispatch_end + label where the error handling is performed. + + We let COM_QUIT and COM_STMT_CLOSE to execute even if wsrep aborted. + (see MDEV-10812). + */ + if (thd->wsrep_conflict_state() == ABORTED) { - my_message(ER_LOCK_DEADLOCK, "Deadlock: wsrep aborted transaction", - MYF(0)); - WSREP_DEBUG("Deadlock error for: %s", thd->query()); - mysql_mutex_unlock(&thd->LOCK_thd_data); - thd->reset_killed(); - thd->mysys_var->abort = 0; - thd->wsrep_conflict_state = NO_CONFLICT; - thd->wsrep_retry_counter = 0; - goto dispatch_end; + thd->store_globals(); + WSREP_LOG_THD(thd, "enter found BF aborted"); + DBUG_ASSERT(!thd->get_stmt_da()->is_set()); + + if (command == COM_STMT_PREPARE || + command == COM_STMT_FETCH || + command == COM_STMT_SEND_LONG_DATA || + command == COM_STMT_CLOSE || + command == COM_QUIT + ) + { + WSREP_DEBUG("Prepared Statement bail out or COM_QUIT"); + } + else + { + thd->reset_killed(); + thd->mysys_var->abort = 0; + thd->wsrep_retry_counter = 0; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); +#ifdef WSREP_TODO + /* + Increment threads running to compensate dec_thread_running() called + after dispatch_end label. + */ + inc_thread_running(); +#endif /* WSREP_TODO */ + goto dispatch_end; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } } mysql_mutex_unlock(&thd->LOCK_thd_data); } @@ -1656,6 +1626,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd, */ thd->set_query_id(get_query_id()); } +#ifdef WITH_WSREP + if (WSREP(thd) && thd->wsrep_next_trx_id() == WSREP_UNDEFINED_TRX_ID) + { + thd->set_wsrep_next_trx_id(thd->query_id); + WSREP_DEBUG("assigned new next trx id: %lu", thd->wsrep_next_trx_id()); + } +#endif /* WITH_WSREP */ if (!(server_command_flags[command] & CF_SKIP_QUESTIONS)) statistic_increment(thd->status_var.questions, &LOCK_status); @@ -1840,8 +1817,29 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; if (WSREP_ON) - wsrep_mysql_parse(thd, thd->query(), thd->query_length(), &parser_state, - is_com_multi, is_next_command); + { + if (wsrep_mysql_parse(thd, thd->query(), thd->query_length(), + &parser_state, + is_com_multi, is_next_command)) + { + WSREP_DEBUG("Deadlock error for: %s", thd->query()); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->killed = NOT_KILLED; + thd->mysys_var->abort = 0; +#ifdef WITH_WSREP + thd->wsrep_retry_counter = 0; +#endif + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); +#ifdef WSREP_TODO + /* + Increment threads running to compensate dec_thread_running() called + after dispatch_end label. + */ + inc_thread_running(); +#endif /* WSREP_TODO */ + goto dispatch_end; + } + } else mysql_parse(thd, thd->query(), thd->query_length(), &parser_state, is_com_multi, is_next_command); @@ -1930,8 +1928,30 @@ bool dispatch_command(enum enum_server_command command, THD *thd, parser_state.reset(beginning_of_next_stmt, length); if (WSREP_ON) - wsrep_mysql_parse(thd, beginning_of_next_stmt, length, &parser_state, - is_com_multi, is_next_command); + { + if (wsrep_mysql_parse(thd, beginning_of_next_stmt, + length, &parser_state, + is_com_multi, is_next_command)) + { + WSREP_DEBUG("Deadlock error for: %s", thd->query()); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->killed = NOT_KILLED; + thd->mysys_var->abort = 0; +#ifdef WITH_WSREP + thd->wsrep_retry_counter = 0; +#endif + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); +#ifdef WSREP_TODO + /* + Increment threads running to compensate dec_thread_running() called + after dispatch_end label. + */ + inc_thread_running(); +#endif /* WSREP_TODO */ + + goto dispatch_end; + } + } else mysql_parse(thd, beginning_of_next_stmt, length, &parser_state, is_com_multi, is_next_command); @@ -2367,10 +2387,10 @@ com_multi_end: break; } -#ifdef WITH_WSREP dispatch_end: +#ifdef WITH_WSREP - if (WSREP(thd)) + if (wsrep_on) { /* MDEV-10812 @@ -2378,15 +2398,51 @@ com_multi_end: */ DBUG_ASSERT((command != COM_QUIT && command != COM_STMT_CLOSE) || thd->get_stmt_da()->is_disabled()); - /* wsrep BF abort in query exec phase */ - mysql_mutex_lock(&thd->LOCK_thd_data); - do_end_of_statement= thd->wsrep_conflict_state != REPLAYING && - thd->wsrep_conflict_state != RETRY_AUTOCOMMIT; - mysql_mutex_unlock(&thd->LOCK_thd_data); - } - else - do_end_of_statement= true; + /* + BF aborted before sending response back to client + */ + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + do_end_of_statement= thd->wsrep_conflict_state() != REPLAYING && + thd->wsrep_conflict_state() != RETRY_AUTOCOMMIT; + if (thd->wsrep_conflict_state() == MUST_ABORT) + { + wsrep_client_rollback(thd); + wsrep_post_rollback(thd); + DBUG_ASSERT(thd->wsrep_conflict_state() == ABORTED); + } + if (thd->wsrep_conflict_state() == ABORTED && + !(command == COM_STMT_PREPARE || + command == COM_STMT_FETCH || + command == COM_STMT_SEND_LONG_DATA || + command == COM_STMT_CLOSE || + command == COM_QUIT + )) + { + wsrep_override_error(thd, ER_LOCK_DEADLOCK); + wsrep_cleanup_transaction(thd); + WSREP_LOG_THD(thd, "leave"); + } + + /* + Final check after sending response back to client. Handle possible + BF abort and query state change atomically. Don't call + wsrep_cleanup_transaction() to leave thd->wsrep_conflict_state() + to ABORTED so that the rollback will be detected when the client + returns to action. + */ + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state() == MUST_ABORT) + { + wsrep_client_rollback(thd); + wsrep_post_rollback(thd); + WSREP_LOG_THD(thd, "after return to client found BF aborted"); + } + thd->set_wsrep_query_state(QUERY_IDLE); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } else { /* if (WSREP(thd))... */ + do_end_of_statement= true; + } #endif /* WITH_WSREP */ if (do_end_of_statement) @@ -3414,7 +3470,7 @@ mysql_execute_command(THD *thd) } /* endif unlikely slave */ #endif #ifdef WITH_WSREP - if (wsrep && WSREP(thd)) + if (WSREP(thd)) { /* change LOCK TABLE WRITE to transaction @@ -3444,8 +3500,8 @@ mysql_execute_command(THD *thd) * allow SET and SHOW queries and reads from information schema * and dirty reads (if configured) */ - if (!thd->wsrep_applier && - !(wsrep_ready && wsrep_reject_queries == WSREP_REJECT_NONE) && + if (!(thd->wsrep_applier || thd->wsrep_SR_thd) && + !(wsrep_ready_get() && wsrep_reject_queries == WSREP_REJECT_NONE) && !(thd->variables.wsrep_dirty_reads && (sql_command_flags[lex->sql_command] & CF_CHANGES_DATA) == 0) && !wsrep_tables_accessible_when_detached(all_tables) && @@ -3610,7 +3666,7 @@ mysql_execute_command(THD *thd) not run in it's own transaction it may simply never appear on the slave in case the outside transaction rolls back. */ - if (stmt_causes_implicit_commit(thd, CF_IMPLICT_COMMIT_BEGIN)) + if (stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_BEGIN)) { /* Note that this should never happen inside of stored functions @@ -3681,6 +3737,17 @@ mysql_execute_command(THD *thd) /* Start timeouts */ thd->set_query_timer(); +#ifdef WITH_WSREP + /* + THD is executing non-blocking operation. Set mark that the + execution has made it to actual command execution. + */ + if (thd->wsrep_nbo_ctx) { + DBUG_ASSERT(thd->wsrep_nbo_ctx->executing() == false); + thd->wsrep_nbo_ctx->set_executing(true); + } +#endif /* WITH_WSREP */ + switch (lex->sql_command) { case SQLCOM_SHOW_EVENTS: @@ -3742,12 +3809,17 @@ mysql_execute_command(THD *thd) case SQLCOM_SELECT: { #ifdef WITH_WSREP - if (lex->sql_command == SQLCOM_SELECT) - WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_READ) - else - WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW) + DBUG_ASSERT(thd->wsrep_exec_mode != REPL_RECV); + if (lex->sql_command == SQLCOM_SELECT) + { + WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_READ); + } + else + { + WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW); + } #endif /* WITH_WSREP */ - + thd->status_var.last_query_cost= 0.0; /* @@ -4550,9 +4622,7 @@ end_with_restore_list: WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE); ha_rows found= 0, updated= 0; DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (WSREP_CLIENT(thd) && - wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE)) - goto error; + WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE); if (update_precheck(thd, all_tables)) break; @@ -4701,9 +4771,7 @@ end_with_restore_list: WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE); DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (WSREP_CLIENT(thd) && - wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE)) - goto error; + WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE); /* Since INSERT DELAYED doesn't support temporary tables, we could @@ -4761,9 +4829,7 @@ end_with_restore_list: select_insert *sel_result; bool explain= MY_TEST(lex->describe); DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (WSREP_CLIENT(thd) && - wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE)) - goto error; + WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE); if ((res= insert_precheck(thd, all_tables))) break; @@ -4883,9 +4949,7 @@ end_with_restore_list: WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE); select_result *sel_result=lex->result; DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (WSREP_CLIENT(thd) && - wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE)) - goto error; + WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE); if ((res= delete_precheck(thd, all_tables))) break; @@ -4945,9 +5009,7 @@ end_with_restore_list: DBUG_ASSERT(first_table == all_tables && first_table != 0); TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first; multi_delete *result; - if (WSREP_CLIENT(thd) && - wsrep_sync_wait(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE)) - goto error; + WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE); if ((res= multi_delete_precheck(thd, all_tables))) break; @@ -5121,9 +5183,46 @@ end_with_restore_list: if (check_one_table_access(thd, privilege, all_tables)) goto error; +#ifdef WITH_WSREP + /* + If wsrep_load_data_splitting is configured make LOAD DATA to + replicate on each 10K rows. + + If streaming replication is not configured make LOAD DATA to + replicate on each 1MB. + */ + ulong wsrep_trx_fragment_size_orig= thd->variables.wsrep_trx_fragment_size; + ulong wsrep_trx_fragment_unit_orig= thd->variables.wsrep_trx_fragment_unit; + const bool wsrep_on= WSREP(thd); + if (wsrep_on) + { + if (!wsrep_provider_is_SR_capable() || + !thd->is_current_stmt_binlog_format_row()) + { + thd->variables.wsrep_trx_fragment_size= 0; + } + else if (wsrep_load_data_splitting) + { + thd->variables.wsrep_trx_fragment_size= 10000; + thd->variables.wsrep_trx_fragment_unit= WSREP_FRAG_ROWS; + } + else if (thd->variables.wsrep_trx_fragment_size == 0) + { + thd->variables.wsrep_trx_fragment_size= (1 << 20); + thd->variables.wsrep_trx_fragment_unit= WSREP_FRAG_BYTES; + } + } +#endif /* WITH_WSREP */ res= mysql_load(thd, lex->exchange, first_table, lex->field_list, lex->update_list, lex->value_list, lex->duplicates, lex->ignore, (bool) lex->local_file); +#ifdef WITH_WSREP + if (wsrep_on) + { + thd->variables.wsrep_trx_fragment_size= wsrep_trx_fragment_size_orig; + thd->variables.wsrep_trx_fragment_unit= wsrep_trx_fragment_unit_orig; + } +#endif /* WITH_WSREP */ break; } @@ -5763,6 +5862,7 @@ end_with_restore_list: thd->mdl_context.release_transactional_locks(); WSREP_DEBUG("BEGIN failed, MDL released: %lld", (longlong) thd->thread_id); + WSREP_DEBUG("stmt_da, sql_errno: %d", (thd->get_stmt_da()->is_error()) ? thd->get_stmt_da()->sql_errno() : 0); goto error; } my_ok(thd); @@ -5804,15 +5904,17 @@ end_with_restore_list: } #ifdef WITH_WSREP if (WSREP(thd)) { - - if (thd->wsrep_conflict_state == NO_CONFLICT || - thd->wsrep_conflict_state == REPLAYING) + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state() == NO_CONFLICT || + thd->wsrep_conflict_state() == REPLAYING) { my_ok(thd); } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); } else { #endif /* WITH_WSREP */ - my_ok(thd); + + my_ok(thd); #ifdef WITH_WSREP } #endif /* WITH_WSREP */ @@ -5853,12 +5955,17 @@ end_with_restore_list: thd->set_killed(KILL_CONNECTION); #ifdef WITH_WSREP if (WSREP(thd)) { - if (thd->wsrep_conflict_state == NO_CONFLICT) { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + bool send_ok= (thd->wsrep_conflict_state() == NO_CONFLICT || + thd->wsrep_conflict_state() == REPLAYING); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + if (send_ok) + { my_ok(thd); } } else { #endif /* WITH_WSREP */ - my_ok(thd); + my_ok(thd); #ifdef WITH_WSREP } #endif /* WITH_WSREP */ @@ -6305,6 +6412,17 @@ finish: DBUG_ASSERT(!thd->in_active_multi_stmt_transaction() || thd->in_multi_stmt_transaction_mode()); +#ifdef WITH_WSREP + /* + Thread was executing non-blocking operation. Total order isolation + has been released after locking table names. We need to grab + total order isolation section here again to commit/binlog in order. + */ + if (thd->wsrep_nbo_ctx) + { + wsrep_end_nbo_lock(thd, first_table); + } +#endif /* WITH_WSREP */ lex->unit.cleanup(); @@ -6331,25 +6449,6 @@ finish: THD_STAGE_INFO(thd, stage_rollback); trans_rollback_stmt(thd); } -#ifdef WITH_WSREP - if (thd->spcont && - (thd->wsrep_conflict_state == MUST_ABORT || - thd->wsrep_conflict_state == ABORTED || - thd->wsrep_conflict_state == CERT_FAILURE)) - { - /* - The error was cleared, but THD was aborted by wsrep and - wsrep_conflict_state is still set accordingly. This - situation is expected if we are running a stored procedure - that declares a handler that catches ER_LOCK_DEADLOCK error. - In which case the error may have been cleared in method - sp_rcontext::handle_sql_condition(). - */ - trans_rollback_stmt(thd); - thd->wsrep_conflict_state= NO_CONFLICT; - thd->killed= NOT_KILLED; - } -#endif /* WITH_WSREP */ else { /* If commit fails, we should be able to reset the OK status. */ @@ -6365,9 +6464,6 @@ finish: /* Free tables. Set stage 'closing tables' */ close_thread_tables(thd); -#ifdef WITH_WSREP - thd->wsrep_consistency_check= NO_CONSISTENCY_CHECK; -#endif /* WITH_WSREP */ #ifndef DBUG_OFF @@ -6429,9 +6525,10 @@ finish: TRANSACT_TRACKER(add_trx_state_from_thd(thd)); - WSREP_TO_ISOLATION_END; - #ifdef WITH_WSREP + thd->wsrep_consistency_check= NO_CONSISTENCY_CHECK; + + WSREP_TO_ISOLATION_END; /* Force release of transactional locks if not in active MST and wsrep is on. */ @@ -6444,11 +6541,18 @@ finish: (longlong) thd->thread_id); thd->mdl_context.release_transactional_locks(); } + + /* + Non-blocking operation finished execution. + */ + if (thd->wsrep_nbo_ctx) thd->wsrep_nbo_ctx->set_executing(false); + + /* assume PA safety for next transaction */ + thd->wsrep_PA_safe= true; #endif /* WITH_WSREP */ DBUG_RETURN(res || thd->is_error()); -} - + } static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables) { @@ -6568,12 +6672,12 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables) return res; } - static bool execute_show_status(THD *thd, TABLE_LIST *all_tables) { bool res; system_status_var old_status_var= thd->status_var; thd->initial_status_var= &old_status_var; + WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW); if (!(res= check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE))) res= execute_sqlcom_select(thd, all_tables); @@ -6592,6 +6696,8 @@ static bool execute_show_status(THD *thd, TABLE_LIST *all_tables) offsetof(STATUS_VAR, last_cleared_system_status_var)); mysql_mutex_unlock(&LOCK_status); return res; + error: + return true; } @@ -7833,22 +7939,23 @@ void mysql_init_multi_delete(LEX *lex) lex->query_tables_last= &lex->query_tables; } -static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, +static bool wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, Parser_state *parser_state, bool is_com_multi, bool is_next_command) { #ifdef WITH_WSREP + mysql_mutex_lock(&thd->LOCK_wsrep_thd); bool is_autocommit= - !thd->in_multi_stmt_transaction_mode() && - thd->wsrep_conflict_state == NO_CONFLICT && + !thd->in_multi_stmt_transaction_mode() && + thd->wsrep_conflict_state() == NO_CONFLICT && !thd->wsrep_applier; do { - if (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT) + if (thd->wsrep_conflict_state() == RETRY_AUTOCOMMIT) { - thd->wsrep_conflict_state= NO_CONFLICT; + thd->set_wsrep_conflict_state(NO_CONFLICT); /* Performance Schema Interface instrumentation, begin */ thd->m_statement_psi= MYSQL_REFINE_STATEMENT(thd->m_statement_psi, com_statement_info[thd->get_command()].m_key); @@ -7864,21 +7971,32 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); }); } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); mysql_parse(thd, rawbuf, length, parser_state, is_com_multi, is_next_command); + (void) wsrep_after_command(thd, !thd->in_active_multi_stmt_transaction()); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + /* + State after after_command hook must be either NO_CONFLICT + or MUST_ABORT if the BF abort happened just after leaving + after_command hook. + */ + DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT || + thd->wsrep_conflict_state() == MUST_ABORT || + thd->wsrep_conflict_state() == RETRY_AUTOCOMMIT); if (WSREP(thd)) { /* wsrep BF abort in query exec phase */ - mysql_mutex_lock(&thd->LOCK_thd_data); - if (thd->wsrep_conflict_state == MUST_ABORT) { + if (thd->wsrep_conflict_state() == MUST_ABORT) { wsrep_client_rollback(thd); WSREP_DEBUG("abort in exec query state, avoiding autocommit"); } - if (thd->wsrep_conflict_state == MUST_REPLAY) + /* note: this is obsolete, comin from 10.3.6 merging */ + if (thd->wsrep_conflict_state() == MUST_REPLAY) { - mysql_mutex_unlock(&thd->LOCK_thd_data); + WSREP_WARN("EXPLAIN DELETED"); if (thd->lex->explain) delete_explain_query(thd->lex); mysql_mutex_lock(&thd->LOCK_thd_data); @@ -7886,17 +8004,20 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, wsrep_replay_transaction(thd); } - /* setting error code for BF aborted trxs */ - if (thd->wsrep_conflict_state == ABORTED || - thd->wsrep_conflict_state == CERT_FAILURE) + if (thd->wsrep_conflict_state() == RETRY_AUTOCOMMIT) { thd->reset_for_next_command(); if (is_autocommit && thd->lex->sql_command != SQLCOM_SELECT && (thd->wsrep_retry_counter < thd->variables.wsrep_retry_autocommit)) { - WSREP_DEBUG("wsrep retrying AC query: %s", - (thd->query()) ? thd->query() : "void"); + WSREP_DEBUG("wsrep retrying AC query: %lu %s", + thd->wsrep_retry_counter, WSREP_QUERY(thd)); + + // close_thread_tables(thd); + + assert(LOCAL_ROLLBACK != thd->wsrep_exec_mode); + assert(LOCAL_STATE == thd->wsrep_exec_mode); /* Performance Schema Interface instrumentation, end */ MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da()); @@ -7904,53 +8025,99 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, thd->m_digest= NULL; close_thread_tables(thd); - thd->wsrep_conflict_state= RETRY_AUTOCOMMIT; thd->wsrep_retry_counter++; // grow wsrep_copy_query(thd); thd->set_time(); parser_state->reset(rawbuf, length); +#ifdef OUT + /* PSI end */ + MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da()); + thd->m_statement_psi= NULL; + thd->m_digest= NULL; + + /* DTRACE end */ + if (MYSQL_QUERY_DONE_ENABLED()) + { + WSREP_WARN("DTRACE END"); + MYSQL_QUERY_DONE(thd->is_error()); + } + + /* SHOW PROFILE end */ +#if defined(ENABLED_PROFILING) + thd->profiling.finish_current_query(); +#endif + + /* SHOW PROFILE begin */ +#if defined(ENABLED_PROFILING) + thd->profiling.start_new_query("continuing"); + thd->profiling.set_query_source(rawbuf, length); +#endif + + /* DTRACE begin */ + MYSQL_QUERY_START(rawbuf, thd->thread_id, + (char *) (thd->db ? thd->db : ""), + &thd->security_ctx->priv_user[0], + (char *) thd->security_ctx->host_or_ip); + + /* PSI begin */ + thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state, + com_statement_info[thd->get_command()].m_key, + thd->db.str, thd->db.length, + thd->charset()); + DBUG_ASSERT(thd->wsrep_next_trx_id() == WSREP_UNDEFINED_TRX_ID); +#endif + thd->set_wsrep_next_trx_id(thd->query_id); + WSREP_DEBUG("assigned new next trx id: %lu", thd->wsrep_next_trx_id()); } else { - WSREP_DEBUG("%s, thd: %lld is_AC: %d, retry: %lu - %lu SQL: %s", - (thd->wsrep_conflict_state == ABORTED) ? + WSREP_DEBUG("%s, thd: %lld is_AC: %d, retry: %lu - %lu SQL: %s", + (thd->wsrep_conflict_state_unsafe() == ABORTED) ? "BF Aborted" : "cert failure", (longlong) thd->thread_id, is_autocommit, thd->wsrep_retry_counter, thd->variables.wsrep_retry_autocommit, thd->query()); - my_message(ER_LOCK_DEADLOCK, "Deadlock: wsrep aborted transaction", - MYF(0)); - thd->wsrep_conflict_state= NO_CONFLICT; - if (thd->wsrep_conflict_state != REPLAYING) + /* + mariaDB code use here: + my_message(ER_LOCK_DEADLOCK, "Deadlock: wsrep aborted transaction", + MYF(0)); + But, this breaks many mtr tests where victim deadlock may be + randomly reported by native deadlock error or this mesage. + Fixed this, temporarily, to use native ER_LOCK_DEADLOCK + error, just to get the tests passing + */ + my_error(ER_LOCK_DEADLOCK, MYF(0)); + thd->reset_killed(); + thd->set_wsrep_conflict_state(NO_CONFLICT); + if (thd->wsrep_conflict_state() != REPLAYING) thd->wsrep_retry_counter= 0; // reset } - mysql_mutex_unlock(&thd->LOCK_thd_data); thd->reset_killed(); } else { set_if_smaller(thd->wsrep_retry_counter, 0); // reset; eventually ok - mysql_mutex_unlock(&thd->LOCK_thd_data); } } /* If retry is requested clean up explain structure */ - if ((thd->wsrep_conflict_state == RETRY_AUTOCOMMIT || - thd->wsrep_conflict_state == MUST_REPLAY ) - && thd->lex->explain) + if ((thd->wsrep_conflict_state() == RETRY_AUTOCOMMIT || + thd->wsrep_conflict_state() == MUST_REPLAY ) + && thd->lex->explain) { - delete_explain_query(thd->lex); + delete_explain_query(thd->lex); } - } while (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT); + } while (thd->wsrep_conflict_state()== RETRY_AUTOCOMMIT); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); if (thd->wsrep_retry_query) { WSREP_DEBUG("releasing retry_query: conf %d sent %d kill %d errno %d SQL %s", - thd->wsrep_conflict_state, - thd->get_stmt_da()->is_sent(), + thd->wsrep_conflict_state_unsafe(), + thd->get_stmt_da()->is_sent(), thd->killed, - thd->get_stmt_da()->is_error() ? thd->get_stmt_da()->sql_errno() : 0, + thd->get_stmt_da()->is_error() ? thd->get_stmt_da()->sql_errno() : 0, thd->wsrep_retry_query); my_free(thd->wsrep_retry_query); thd->wsrep_retry_query = NULL; @@ -7958,6 +8125,7 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, thd->wsrep_retry_command = COM_CONNECT; } #endif /* WITH_WSREP */ + return false; } /* @@ -8909,6 +9077,7 @@ THD *find_thread_by_id(longlong id, bool query_id) continue; if (id == (query_id ? tmp->query_id : (longlong) tmp->thread_id)) { + if (WSREP(tmp)) mysql_mutex_lock(&tmp->LOCK_wsrep_thd); mysql_mutex_lock(&tmp->LOCK_thd_kill); // Lock from delete break; } @@ -8937,7 +9106,7 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ uint error= (type == KILL_TYPE_QUERY ? ER_NO_SUCH_QUERY : ER_NO_SUCH_THREAD); DBUG_ENTER("kill_one_thread"); DBUG_PRINT("enter", ("id: %lld signal: %u", id, (uint) kill_signal)); - + WSREP_DEBUG("kill_one_thread %lu", thd->thread_id); if (id && (tmp= find_thread_by_id(id, type == KILL_TYPE_QUERY))) { /* @@ -8963,15 +9132,18 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ if (((thd->security_ctx->master_access & SUPER_ACL) || thd->security_ctx->user_matches(tmp->security_ctx)) && - !wsrep_thd_is_BF(tmp, false)) + !wsrep_thd_is_BF((void*)tmp, false)) { + //if (WSREP(tmp)) mysql_mutex_lock(&tmp->LOCK_wsrep_thd); tmp->awake_no_mutex(kill_signal); + //if (WSREP(tmp)) mysql_mutex_unlock(&tmp->LOCK_wsrep_thd); error=0; } else error= (type == KILL_TYPE_QUERY ? ER_KILL_QUERY_DENIED_ERROR : ER_KILL_DENIED_ERROR); mysql_mutex_unlock(&tmp->LOCK_thd_kill); + if (WSREP(tmp)) mysql_mutex_unlock(&tmp->LOCK_wsrep_thd); } DBUG_PRINT("exit", ("%d", error)); DBUG_RETURN(error); @@ -9029,7 +9201,10 @@ static uint kill_threads_for_user(THD *thd, LEX_USER *user, DBUG_RETURN(ER_KILL_DENIED_ERROR); } if (!threads_to_kill.push_back(tmp, thd->mem_root)) + { + if (WSREP(tmp)) mysql_mutex_lock(&tmp->LOCK_wsrep_thd); mysql_mutex_lock(&tmp->LOCK_thd_kill); // Lock from delete + } } } mysql_mutex_unlock(&LOCK_thread_count); @@ -9051,6 +9226,7 @@ static uint kill_threads_for_user(THD *thd, LEX_USER *user, */ next_ptr= it2++; mysql_mutex_unlock(&ptr->LOCK_thd_kill); + if (WSREP(ptr)) mysql_mutex_unlock(&ptr->LOCK_wsrep_thd); (*rows)++; } while ((ptr= next_ptr)); } diff --git a/sql/sql_parse.h b/sql/sql_parse.h index 1027872898a..e2578b1e363 100644 --- a/sql/sql_parse.h +++ b/sql/sql_parse.h @@ -37,6 +37,8 @@ int test_if_data_home_dir(const char *dir); int error_if_data_home_dir(const char *path, const char *what); my_bool net_allocate_new_packet(NET *net, void *thd, uint my_flags); +bool stmt_causes_implicit_commit(const THD *thd, uint mask); + bool multi_update_precheck(THD *thd, TABLE_LIST *tables); bool multi_delete_precheck(THD *thd, TABLE_LIST *tables); int mysql_multi_update_prepare(THD *thd); diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 8c231d9b8f7..4c72e890e74 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -2281,6 +2281,10 @@ static bool do_uninstall(THD *thd, TABLE *table, const LEX_CSTRING *name) } } return 0; +#ifdef WITH_WSREP + error: +#endif /* WITH_WSREP */ + return 1; } @@ -2299,6 +2303,7 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_CSTRING *name, if (!opt_noacl && check_table_access(thd, DELETE_ACL, &tables, FALSE, 1, FALSE)) DBUG_RETURN(TRUE); + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) diff --git a/sql/sql_plugin_services.ic b/sql/sql_plugin_services.ic index 47decf38973..64c3396c230 100644 --- a/sql/sql_plugin_services.ic +++ b/sql/sql_plugin_services.ic @@ -150,21 +150,17 @@ static struct wsrep_service_st wsrep_handler = { get_wsrep_load_data_splitting, get_wsrep_log_conflicts, get_wsrep_protocol_version, - wsrep_aborting_thd_contains, - wsrep_aborting_thd_enqueue, wsrep_consistency_check, wsrep_is_wsrep_xid, wsrep_xid_seqno, wsrep_xid_uuid, - wsrep_lock_rollback, wsrep_on, - wsrep_post_commit, - wsrep_prepare_key, - wsrep_run_wsrep_commit, + wsrep_prepare_key_for_innodb, wsrep_thd_LOCK, wsrep_thd_UNLOCK, wsrep_thd_awake, wsrep_thd_conflict_state, + wsrep_thd_thread_id, wsrep_thd_conflict_state_str, wsrep_thd_exec_mode, wsrep_thd_exec_mode_str, @@ -181,7 +177,6 @@ static struct wsrep_service_st wsrep_handler = { wsrep_thd_ws_handle, wsrep_trx_is_aborting, wsrep_trx_order_before, - wsrep_unlock_rollback }; static struct thd_specifics_service_st thd_specifics_handler= diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index c615356b354..c9a36b02fe4 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -4198,13 +4198,13 @@ reexecute: if (WSREP_ON) { mysql_mutex_lock(&thd->LOCK_thd_data); - switch (thd->wsrep_conflict_state) + switch (thd->wsrep_conflict_state()) { case CERT_FAILURE: WSREP_DEBUG("PS execute fail for CERT_FAILURE: thd: %lld err: %d", (longlong) thd->thread_id, thd->get_stmt_da()->sql_errno() ); - thd->wsrep_conflict_state = NO_CONFLICT; + thd->set_wsrep_conflict_state(NO_CONFLICT); break; case MUST_REPLAY: @@ -4394,13 +4394,13 @@ reexecute: if (WSREP_ON) { mysql_mutex_lock(&thd->LOCK_thd_data); - switch (thd->wsrep_conflict_state) + switch (thd->wsrep_conflict_state()) { case CERT_FAILURE: WSREP_DEBUG("PS execute fail for CERT_FAILURE: thd: %lld err: %d", (longlong) thd->thread_id, thd->get_stmt_da()->sql_errno() ); - thd->wsrep_conflict_state = NO_CONFLICT; + thd->set_wsrep_conflict_state(NO_CONFLICT); break; case MUST_REPLAY: diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 2ee175293de..1847416368a 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -3845,6 +3845,17 @@ int reset_master(THD* thd, rpl_gtid *init_state, uint32 init_state_len, return 1; } +#ifdef WITH_WSREP + if (WSREP_ON) + { + /* RESET MASTER will initialize GTID sequence, and that would happen locally + in this node, so better reject it + */ + my_message(ER_NOT_ALLOWED_COMMAND, + "RESET MASTER not allowed when node is in cluster", MYF(0)); + return 1; + } +#endif /* WITH_WSREP */ bool ret= 0; /* Temporarily disable master semisync before reseting master. */ repl_semisync_master.before_reset_master(); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 08e1c1c69d3..3d6d60811af 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2650,7 +2650,7 @@ err: int error_code = non_tmp_error ? thd->get_stmt_da()->sql_errno() : 0; #ifdef WITH_WSREP - thd->wsrep_skip_wsrep_GTID = false; + thd->wsrep_skip_wsrep_GTID = true; #endif /* WITH_WSREP */ error |= thd->binlog_query(THD::STMT_QUERY_TYPE, built_query.ptr(), @@ -2701,7 +2701,7 @@ err: end: #ifdef WITH_WSREP - thd->wsrep_skip_wsrep_GTID = false; + thd->wsrep_skip_wsrep_GTID = false; #endif /* WITH_WSREP */ DBUG_RETURN(error); } @@ -7560,6 +7560,19 @@ static bool mysql_inplace_alter_table(THD *thd, } } +#ifdef WITH_WSREP + if (thd->wsrep_nbo_ctx) { + wsrep_begin_nbo_unlock(thd); + } + DBUG_EXECUTE_IF("sync.alter_locked_tables_inplace", + { + const char act[]= + "now " + "wait_for signal.alter_locked_tables_inplace"; + DBUG_ASSERT(!debug_sync_set_action(thd, + STRING_WITH_LEN(act))); + };); +#endif /* WITH_WSREP */ DEBUG_SYNC(thd, "alter_table_inplace_after_lock_downgrade"); THD_STAGE_INFO(thd, stage_alter_inplace); @@ -9782,6 +9795,21 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL); } +#ifdef WITH_WSREP + if (thd->wsrep_nbo_ctx) { + wsrep_begin_nbo_unlock(thd); + } + + DBUG_EXECUTE_IF("sync.alter_locked_tables", + { + const char act[]= + "now " + "wait_for signal.alter_locked_tables"; + DBUG_ASSERT(!debug_sync_set_action(thd, + STRING_WITH_LEN(act))); + };); + +#endif /* WITH_WSREP */ /* Open the table since we need to copy the data. */ if (table->s->tmp_table != NO_TMP_TABLE) diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index d515aacd1d0..2239afbb13b 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -416,8 +416,22 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref) if (WSREP(thd) && wsrep_to_isolation_begin(thd, table_ref->db.str, table_ref->table_name.str, 0)) DBUG_RETURN(TRUE); - if (lock_table(thd, table_ref, &hton_can_recreate)) - DBUG_RETURN(TRUE); + + /* + When using non-blocking operation for TRUNCATE always fall to + handler_truncate() in order to avoid calling lock_table_names() + twice. + */ +#ifdef WITH_WSREP + if (WSREP(thd) && thd->wsrep_nbo_ctx) { + hton_can_recreate= false; + } + else +#endif + { + if (lock_table(thd, table_ref, &hton_can_recreate)) + DBUG_RETURN(TRUE); + } if (hton_can_recreate) { diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 75a962939ae..464ba06ddf9 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -5401,7 +5401,7 @@ static Sys_var_ulong Sys_wsrep_max_ws_size ( GLOBAL_VAR(wsrep_max_ws_size), CMD_LINE(REQUIRED_ARG), VALID_RANGE(1024, WSREP_MAX_WS_SIZE), DEFAULT(WSREP_MAX_WS_SIZE), BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, - ON_CHECK(wsrep_max_ws_size_check), ON_UPDATE(wsrep_max_ws_size_update)); + ON_CHECK(0), ON_UPDATE(wsrep_max_ws_size_update)); static Sys_var_ulong Sys_wsrep_max_ws_rows ( "wsrep_max_ws_rows", "Max number of rows in write set", @@ -5438,7 +5438,7 @@ static Sys_var_uint Sys_wsrep_sync_wait( NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(wsrep_sync_wait_update)); -static const char *wsrep_OSU_method_names[]= { "TOI", "RSU", NullS }; +static const char *wsrep_OSU_method_names[]= { "TOI", "RSU", "NBO", NullS }; static Sys_var_enum Sys_wsrep_OSU_method( "wsrep_OSU_method", "Method for Online Schema Upgrade", SESSION_VAR(wsrep_OSU_method), CMD_LINE(OPT_ARG), @@ -5488,7 +5488,7 @@ static Sys_var_ulong Sys_wsrep_mysql_replication_bundle( static Sys_var_mybool Sys_wsrep_load_data_splitting( "wsrep_load_data_splitting", "To commit LOAD DATA " - "transaction after every 10K rows inserted", + "transaction after every 10K rows inserted (deprecating)", GLOBAL_VAR(wsrep_load_data_splitting), CMD_LINE(OPT_ARG), DEFAULT(TRUE)); @@ -5508,12 +5508,44 @@ static Sys_var_mybool Sys_wsrep_restart_slave( "wsrep_restart_slave", "Should MariaDB slave be restarted automatically, when node joins back to cluster", GLOBAL_VAR(wsrep_restart_slave), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); +static Sys_var_ulong Sys_wsrep_trx_fragment_size( + "wsrep_trx_fragment_size", + "Size of transaction fragments for streaming replication (measured in " + "units of 'wsrep_trx_fragment_unit')", + SESSION_VAR(wsrep_trx_fragment_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, WSREP_MAX_WS_SIZE), DEFAULT(0), BLOCK_SIZE(1), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(wsrep_trx_fragment_size_check)); + +extern const char *wsrep_fragment_units[]; + +static Sys_var_enum Sys_wsrep_trx_fragment_unit( + "wsrep_trx_fragment_unit", + "Unit for streaming replication transaction fragments' size: bytes, " + "events, rows, statements", + SESSION_VAR(wsrep_trx_fragment_unit), CMD_LINE(REQUIRED_ARG), + wsrep_fragment_units, + DEFAULT(WSREP_FRAG_BYTES), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(0)); + +extern const char *wsrep_SR_store_types[]; +static Sys_var_enum Sys_wsrep_SR_store( + "wsrep_SR_store", "Storage for streaming replication fragments", + READ_ONLY GLOBAL_VAR(wsrep_SR_store_type), CMD_LINE(REQUIRED_ARG), + wsrep_SR_store_types, DEFAULT(WSREP_SR_STORE_TABLE), + NO_MUTEX_GUARD, NOT_IN_BINLOG); + static Sys_var_mybool Sys_wsrep_dirty_reads( "wsrep_dirty_reads", "Allow reads even when the node is not in the primary component.", SESSION_VAR(wsrep_dirty_reads), CMD_LINE(OPT_ARG), DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG); +static Sys_var_uint Sys_wsrep_ignore_apply_errors ( + "wsrep_ignore_apply_errors", "Ignore replication errors", + GLOBAL_VAR(wsrep_ignore_apply_errors), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(WSREP_IGNORE_ERRORS_NONE, WSREP_IGNORE_ERRORS_MAX), + DEFAULT(7), BLOCK_SIZE(1)); + static Sys_var_uint Sys_wsrep_gtid_domain_id( "wsrep_gtid_domain_id", "When wsrep_gtid_mode is set, this value is " "used as gtid_domain_id for galera transactions and also copied to the " diff --git a/sql/table.cc b/sql/table.cc index e98836cd93c..e82092b1820 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -249,6 +249,13 @@ TABLE_CATEGORY get_table_category(const LEX_CSTRING *db, DBUG_ASSERT(db != NULL); DBUG_ASSERT(name != NULL); +#ifdef WITH_WSREP + if (my_strcasecmp(system_charset_info, db->str, "wsrep_schema") == 0 && + my_strcasecmp(system_charset_info, name->str, "SR") == 0) + { + return TABLE_CATEGORY_INFORMATION; + } +#endif /* WITH_WSREP */ if (is_infoschema_db(db)) return TABLE_CATEGORY_INFORMATION; diff --git a/sql/transaction.cc b/sql/transaction.cc index 1c2820200d1..8978ed18923 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -135,8 +135,6 @@ static bool xa_trans_force_rollback(THD *thd) by ha_rollback()/THD::transaction::cleanup(). */ thd->transaction.xid_state.rm_error= 0; - if (WSREP_ON) - wsrep_register_hton(thd, TRUE); if (ha_rollback_trans(thd, true)) { my_error(ER_XAER_RMERR, MYF(0)); @@ -184,14 +182,10 @@ bool trans_begin(THD *thd, uint flags) (thd->variables.option_bits & OPTION_TABLE_LOCK)) { thd->variables.option_bits&= ~OPTION_TABLE_LOCK; - if (WSREP_ON) - wsrep_register_hton(thd, TRUE); thd->server_status&= ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); res= MY_TEST(ha_commit_trans(thd, TRUE)); - if (WSREP_ON) - wsrep_post_commit(thd, TRUE); } thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); @@ -252,7 +246,6 @@ bool trans_begin(THD *thd, uint flags) } #ifdef WITH_WSREP - thd->wsrep_PA_safe= true; if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd)) DBUG_RETURN(TRUE); #endif /* WITH_WSREP */ @@ -299,8 +292,6 @@ bool trans_commit(THD *thd) if (trans_check(thd)) DBUG_RETURN(TRUE); - if (WSREP_ON) - wsrep_register_hton(thd, TRUE); thd->server_status&= ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); @@ -311,8 +302,6 @@ bool trans_commit(THD *thd) mysql_mutex_assert_not_owner(&LOCK_after_binlog_sync); mysql_mutex_assert_not_owner(&LOCK_commit_ordered); - if (WSREP_ON) - wsrep_post_commit(thd, TRUE); /* if res is non-zero, then ha_commit_trans has rolled back the transaction, so the hooks for rollback will be called. @@ -368,14 +357,10 @@ bool trans_commit_implicit(THD *thd) /* Safety if one did "drop table" on locked tables */ if (!thd->locked_tables_mode) thd->variables.option_bits&= ~OPTION_TABLE_LOCK; - if (WSREP_ON) - wsrep_register_hton(thd, TRUE); thd->server_status&= ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); res= MY_TEST(ha_commit_trans(thd, TRUE)); - if (WSREP_ON) - wsrep_post_commit(thd, TRUE); } thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); @@ -409,14 +394,9 @@ bool trans_rollback(THD *thd) int res; DBUG_ENTER("trans_rollback"); -#ifdef WITH_WSREP - thd->wsrep_PA_safe= true; -#endif /* WITH_WSREP */ if (trans_check(thd)) DBUG_RETURN(TRUE); - if (WSREP_ON) - wsrep_register_hton(thd, TRUE); thd->server_status&= ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); @@ -424,6 +404,7 @@ bool trans_rollback(THD *thd) #ifdef HAVE_REPLICATION repl_semisync_master.wait_after_rollback(thd, FALSE); #endif + //(void) RUN_HOOK(transaction, after_rollback, (thd, FALSE)); thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); /* Reset the binlog transaction marker */ thd->variables.option_bits&= ~OPTION_GTID_BEGIN; @@ -515,14 +496,10 @@ bool trans_commit_stmt(THD *thd) if (thd->transaction.stmt.ha_list) { - if (WSREP_ON) - wsrep_register_hton(thd, FALSE); res= ha_commit_trans(thd, FALSE); if (! thd->in_active_multi_stmt_transaction()) { trans_reset_one_shot_chistics(thd); - if (WSREP_ON) - wsrep_post_commit(thd, FALSE); } } @@ -578,8 +555,6 @@ bool trans_rollback_stmt(THD *thd) if (thd->transaction.stmt.ha_list) { - if (WSREP_ON) - wsrep_register_hton(thd, FALSE); ha_rollback_trans(thd, FALSE); if (! thd->in_active_multi_stmt_transaction()) trans_reset_one_shot_chistics(thd); @@ -733,7 +708,8 @@ bool trans_rollback_to_savepoint(THD *thd, LEX_CSTRING name) logging is off. */ bool mdl_can_safely_rollback_to_savepoint= - (!(mysql_bin_log.is_open() && thd->variables.sql_log_bin) || + (!((WSREP_EMULATE_BINLOG_NNULL(thd) || mysql_bin_log.is_open()) + && thd->variables.sql_log_bin) || ha_rollback_to_savepoint_can_release_mdl(thd)); if (ha_rollback_to_savepoint(thd, sv)) @@ -944,13 +920,9 @@ bool trans_xa_commit(THD *thd) } else if (xa_state == XA_IDLE && thd->lex->xa_opt == XA_ONE_PHASE) { - if (WSREP_ON) - wsrep_register_hton(thd, TRUE); int r= ha_commit_trans(thd, TRUE); if ((res= MY_TEST(r))) my_error(r == 1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0)); - if (WSREP_ON) - wsrep_post_commit(thd, TRUE); } else if (xa_state == XA_PREPARED && thd->lex->xa_opt == XA_NONE) { @@ -969,8 +941,6 @@ bool trans_xa_commit(THD *thd) if (thd->mdl_context.acquire_lock(&mdl_request, thd->variables.lock_wait_timeout)) { - if (WSREP_ON) - wsrep_register_hton(thd, TRUE); ha_rollback_trans(thd, TRUE); my_error(ER_XAER_RMERR, MYF(0)); } diff --git a/sql/wsrep_applier.cc b/sql/wsrep_applier.cc index f2d90def5ef..e3de1e160a4 100644 --- a/sql/wsrep_applier.cc +++ b/sql/wsrep_applier.cc @@ -14,10 +14,15 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "mariadb.h" +#include "my_pthread.h" #include "wsrep_priv.h" #include "wsrep_binlog.h" // wsrep_dump_rbr_buf() #include "wsrep_xid.h" +#include "wsrep_sr.h" +#include "wsrep_thd.h" +#include "wsrep_trans_observer.h" +#include "slave.h" // opt_log_slave_updates #include "log_event.h" // class THD, EVENT_LEN_OFFSET, etc. #include "wsrep_applier.h" #include "debug_sync.h" @@ -62,7 +67,7 @@ void wsrep_set_apply_format(THD* thd, Format_description_log_event* ev) { if (thd->wsrep_apply_format) { - delete (Format_description_log_event*)thd->wsrep_apply_format; + delete (Format_description_log_event*)thd->wsrep_apply_format; } thd->wsrep_apply_format= ev; } @@ -79,9 +84,56 @@ Format_description_log_event* wsrep_get_apply_format(THD* thd) return thd->wsrep_rgi->rli->relay_log.description_event_for_exec; } -static wsrep_cb_status_t wsrep_apply_events(THD* thd, - const void* events_buf, - size_t buf_len) +void wsrep_apply_error::store(const THD* const thd) +{ + Diagnostics_area::Sql_condition_iterator it= + thd->get_stmt_da()->sql_conditions(); + const Sql_condition* cond; + + static size_t const max_len= 2*MAX_SLAVE_ERRMSG; // 2x so that we have enough + + if (NULL == str_) + { + // this must be freeable by standard free() + str_= static_cast<char*>(malloc(max_len)); + if (NULL == str_) + { + WSREP_ERROR("Failed to allocate %zu bytes for error buffer.", max_len); + len_ = 0; + return; + } + } + else + { + /* This is possible when we invoke rollback after failed applying. + * In this situation DA should not be reset yet and should contain + * all previous errors from applying and new ones from rollbacking, + * so we just overwrite is from scratch */ + } + + char* slider= str_; + const char* const buf_end= str_ + max_len - 1; // -1: leave space for \0 + + for (cond= it++; cond && slider < buf_end; cond= it++) + { + uint const err_code= cond->get_sql_errno(); + const char* const err_str= cond->get_message_text(); + + slider+= my_snprintf(slider, buf_end - slider, " %s, Error_code: %d;", + err_str, err_code); + } + + *slider= '\0'; + len_= slider - str_ + 1; // +1: add \0 + + WSREP_DEBUG("Error buffer for thd %llu seqno %lld, %zu bytes: %s", + thd->thread_id, (long long)wsrep_thd_trx_seqno(thd), + len_, str_ ? str_ : "(null)"); +} + +int wsrep_apply_events(THD* thd, + const void* events_buf, + size_t buf_len) { char *buf= (char *)events_buf; int rcode= 0; @@ -91,18 +143,24 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, DBUG_ENTER("wsrep_apply_events"); if (thd->killed == KILL_CONNECTION && - thd->wsrep_conflict_state != REPLAYING) + thd->wsrep_conflict_state() != REPLAYING) { WSREP_INFO("applier has been aborted, skipping apply_rbr: %lld", (long long) wsrep_thd_trx_seqno(thd)); - DBUG_RETURN(WSREP_CB_FAILURE); + DBUG_RETURN(WSREP_ERR_ABORTED); } mysql_mutex_lock(&thd->LOCK_thd_data); - thd->wsrep_query_state= QUERY_EXEC; - if (thd->wsrep_conflict_state!= REPLAYING) - thd->wsrep_conflict_state= NO_CONFLICT; - mysql_mutex_unlock(&thd->LOCK_thd_data); + // thd->set_wsrep_query_state(QUERY_EXEC); + if (thd->wsrep_conflict_state() != REPLAYING) + { + DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT); + if (thd->wsrep_conflict_state() != NO_CONFLICT) + { + thd->set_wsrep_conflict_state(NO_CONFLICT); + } + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); if (!buf_len) WSREP_DEBUG("empty rbr buffer to apply: %lld", (long long) wsrep_thd_trx_seqno(thd)); @@ -117,7 +175,7 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, { WSREP_ERROR("applier could not read binlog event, seqno: %lld, len: %zu", (long long)wsrep_thd_trx_seqno(thd), buf_len); - rcode= 1; + rcode= WSREP_ERR_BAD_EVENT; goto error; } @@ -146,9 +204,6 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, /* Use the original server id for logging. */ thd->set_server_id(ev->server_id); thd->set_time(); // time the query - wsrep_xid_init(&thd->transaction.xid_state.xid, - thd->wsrep_trx_meta.gtid.uuid, - thd->wsrep_trx_meta.gtid.seqno); thd->lex->current_select= 0; if (!ev->when) { @@ -167,7 +222,7 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, if (exec_res) { - WSREP_WARN("RBR event %d %s apply warning: %d, %lld", + WSREP_WARN("Event %d %s apply failed: %d, seqno %lld", event, ev->get_type_str(), exec_res, (long long) wsrep_thd_trx_seqno(thd)); rcode= exec_res; @@ -177,28 +232,30 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, } event++; - if (thd->wsrep_conflict_state!= NO_CONFLICT && - thd->wsrep_conflict_state!= REPLAYING) + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state() != NO_CONFLICT && + thd->wsrep_conflict_state() != REPLAYING) WSREP_WARN("conflict state after RBR event applying: %d, %lld", - thd->wsrep_query_state, (long long)wsrep_thd_trx_seqno(thd)); + thd->wsrep_query_state(), (long long)wsrep_thd_trx_seqno(thd)); - if (thd->wsrep_conflict_state == MUST_ABORT) { - WSREP_WARN("RBR event apply failed, rolling back: %lld", + if (thd->wsrep_conflict_state() == MUST_ABORT) { + WSREP_WARN("Event apply failed, rolling back: %lld", (long long) wsrep_thd_trx_seqno(thd)); trans_rollback(thd); thd->locked_tables_list.unlock_locked_tables(thd); /* Release transactional metadata locks. */ thd->mdl_context.release_transactional_locks(); - thd->wsrep_conflict_state= NO_CONFLICT; - DBUG_RETURN(WSREP_CB_FAILURE); + thd->set_wsrep_conflict_state(NO_CONFLICT); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + DBUG_RETURN(rcode ? rcode : WSREP_ERR_ABORTED); } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); delete_or_keep_event_post_apply(thd->wsrep_rgi, typ, ev); } error: mysql_mutex_lock(&thd->LOCK_thd_data); - thd->wsrep_query_state= QUERY_IDLE; mysql_mutex_unlock(&thd->LOCK_thd_data); assert(thd->wsrep_exec_mode== REPL_RECV); @@ -206,21 +263,208 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, if (thd->killed == KILL_CONNECTION) WSREP_INFO("applier aborted: %lld", (long long)wsrep_thd_trx_seqno(thd)); - if (rcode) DBUG_RETURN(WSREP_CB_FAILURE); - DBUG_RETURN(WSREP_CB_SUCCESS); + DBUG_RETURN(rcode); +} + +static wsrep_SR_trx_info* wsrep_prepare_applier_ctx( + uint32_t const flags, + const wsrep_trx_meta_t* const meta, + THD** thd) +{ + DBUG_ENTER("wsrep_prepare_applier_ctx"); + + THD* const orig_thd(*thd); + wsrep_SR_trx_info* SR_trx(NULL); + + if ((flags & WSREP_FLAG_TRX_START) && + (flags & WSREP_FLAG_TRX_END || flags & WSREP_FLAG_ROLLBACK)) + { + /* non-SR trx */ + (*thd)->store_globals(); + } + else if (!(flags & WSREP_FLAG_TRX_START)) + { + /* continuation of SR trx */ + SR_trx = sr_pool->find(meta->stid.node, meta->stid.trx); + if (NULL == SR_trx) + { + WSREP_DEBUG("SR transaction has been aborted already."); + goto out; + } + /* SR trx write sets cannot be applied in parallel */ + assert(SR_trx->get_applier_thread() == 0); + + /* switch THD contexts */ + SR_trx->set_applier_thread(orig_thd->thread_id); + *thd = SR_trx->get_THD(); + (*thd)->thread_stack = orig_thd->thread_stack; + WSREP_DEBUG("fragment trx found, thread_id: %lld", (*thd)->thread_id); + (*thd)->store_globals(); + } + else + { + assert(flags & WSREP_FLAG_TRX_START); + assert(!(flags & WSREP_FLAG_ROLLBACK)); + + /* starting new streaming replication trx, prepare a new context */ + WSREP_DEBUG("WS with begin and not commit flag"); + *thd = wsrep_start_SR_THD(orig_thd->thread_stack); + SR_trx = sr_pool->add(meta->stid.node, meta->stid.trx, *thd); + + (*thd)->store_globals(); + } + + assert(*thd); + (*thd)->wsrep_trx_meta = *meta; + +out: + DBUG_RETURN(SR_trx); +} + +static inline void wsrep_restore_applier_ctx(wsrep_SR_trx_info* const SR_trx, + THD* const orig_thd) +{ + DBUG_ENTER("wsrep_restore_applier_ctx"); + WSREP_DEBUG("resetting default thd for applier, id: %lld, thd: %p", + orig_thd->thread_id, orig_thd); + SR_trx->set_applier_thread(0); + orig_thd->store_globals(); + DBUG_VOID_RETURN; +} + + +static wsrep_cb_status_t wsrep_rollback_common(THD* thd, wsrep_apply_error& err) +{ + DBUG_ENTER("wsrep_rollback_common"); + wsrep_cb_status_t rcode(WSREP_CB_SUCCESS); + + WSREP_DEBUG("Slave rolling back %lld", (long long)wsrep_thd_trx_seqno(thd)); +//#ifdef WSREP_PROC_INFO + snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, + "rolling back %lld", (long long)wsrep_thd_trx_seqno(thd)); + thd_proc_info(thd, thd->wsrep_info); +//#else +// thd_proc_info(thd, "rolling back"); +//#endif /* WSREP_PROC_INFO */ + + if (thd->wsrep_SR_thd && wsrep_SR_store) + { + /* prevent rollbacker to abort the same thd */ + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_conflict_state(MUST_ABORT); + thd->set_wsrep_conflict_state(ABORTING); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + /* rollback SR trx */ + if (trans_rollback_stmt(thd) || trans_rollback(thd)) + { + rcode = WSREP_CB_FAILURE; + err.store(thd); + } + } + +//#ifdef WSREP_PROC_INFO + snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, + "rolled back %lld", (long long)wsrep_thd_trx_seqno(thd)); + thd_proc_info(thd, thd->wsrep_info); +//#else +// thd_proc_info(thd, "rolled back"); +//#endif /* WSREP_PROC_INFO */ + thd->wsrep_rgi->cleanup_context(thd, 0); +#ifdef GTID_SUPPORT + thd->variables.gtid_next.set_automatic(); +#endif + DBUG_RETURN(rcode); +} + + +static wsrep_cb_status_t wsrep_rollback_trx(THD* thd, + const void* const buf, + size_t const buf_len, + uint32_t const flags, + const wsrep_trx_meta_t* const meta, + wsrep_apply_error& err) +{ + DBUG_ENTER("wsrep_rollback_trx"); + + assert(flags & WSREP_FLAG_ROLLBACK); + + THD* const orig_thd(thd); + + wsrep_SR_trx_info* const SR_trx(wsrep_prepare_applier_ctx(flags, meta, &thd)); + + WSREP_DEBUG("Rollback for: %ld", meta->stid.trx); + + // Preempted by rollbacker + if (!SR_trx && !(flags & WSREP_FLAG_TRX_START)) + { + WSREP_DEBUG("Pre-empted by rollbacker: %ld", + meta->stid.trx); + DBUG_RETURN(WSREP_CB_SUCCESS); + } + + if (SR_trx) + { + /* + TODO: Must be done atomically with writing dummy event, should be + moved into wsrep_rollback_comman(). + */ + wsrep_rollback_SR_trx(thd); + } + + wsrep_cb_status_t const rcode(wsrep_rollback_common(thd, err)); + + if (SR_trx) + { + wsrep_restore_applier_ctx(SR_trx, orig_thd); + } + + DBUG_RETURN(rcode); } -wsrep_cb_status_t wsrep_apply_cb(void* const ctx, - const void* const buf, - size_t const buf_len, - uint32_t const flags, - const wsrep_trx_meta_t* meta) +static int wsrep_apply_trx(THD* orig_thd, + const void* const buf, + size_t const buf_len, + uint32_t const flags, + const wsrep_trx_meta_t* meta, + wsrep_apply_error& err) { - THD* const thd((THD*)ctx); + THD* thd= orig_thd; + DBUG_ENTER("wsrep_apply_trx"); - assert(thd->wsrep_apply_toi == false); + DBUG_ASSERT(thd->wsrep_apply_toi == false); + DBUG_ASSERT(!(flags & WSREP_FLAG_ROLLBACK)); + DBUG_ASSERT(!(flags & WSREP_FLAG_ISOLATION)); + DBUG_ASSERT(err.is_null()); - // Allow tests to block the applier thread using the DBUG facilities. + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state() == REPLAYING && + (flags & WSREP_FLAG_TRX_END) && !(flags & WSREP_FLAG_TRX_START)) + { + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + /* + Replaying, must add final frag to SR storage for actual replay + */ + if (wsrep_SR_store) + { + wsrep_SR_store->append_frag_commit(thd, + flags, + (const uchar*)buf, + buf_len); + DBUG_RETURN(wsrep_replay_from_SR_store(thd, *meta)); + } + DBUG_RETURN(0); + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + wsrep_SR_trx_info* const SR_trx(wsrep_prepare_applier_ctx(flags, meta, &thd)); + + assert(thd); + + /* moved dbug sync point here, after possible THD switch for SR transactions + has ben done + */ + // Allow tests to block the applier thread using the DBUG facilities DBUG_EXECUTE_IF("sync.wsrep_apply_cb", { const char act[]= @@ -231,66 +475,325 @@ wsrep_cb_status_t wsrep_apply_cb(void* const ctx, STRING_WITH_LEN(act))); };); - thd->wsrep_trx_meta = *meta; - -#ifdef WSREP_PROC_INFO - snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, - "Applying write set %lld: %p, %zu", - (long long)wsrep_thd_trx_seqno(thd), buf, buf_len); - thd_proc_info(thd, thd->wsrep_info); -#else - thd_proc_info(thd, "Applying write set"); -#endif /* WSREP_PROC_INFO */ - /* tune FK and UK checking policy */ - if (wsrep_slave_UK_checks == FALSE) + if (wsrep_slave_UK_checks == FALSE) thd->variables.option_bits|= OPTION_RELAXED_UNIQUE_CHECKS; else thd->variables.option_bits&= ~OPTION_RELAXED_UNIQUE_CHECKS; - if (wsrep_slave_FK_checks == FALSE) + if (wsrep_slave_FK_checks == FALSE) thd->variables.option_bits|= OPTION_NO_FOREIGN_KEY_CHECKS; else thd->variables.option_bits&= ~OPTION_NO_FOREIGN_KEY_CHECKS; - /* With galera we assume that the master has done the constraint checks */ - thd->variables.option_bits|= OPTION_NO_CHECK_CONSTRAINT_CHECKS; + /* + Actual applying is done in wsrep_apply_events() + */ + int rcode(wsrep_apply_events(thd, buf, buf_len)); - if (flags & WSREP_FLAG_ISOLATION) + if (0 != rcode || thd->wsrep_has_ignored_error) { - thd->wsrep_apply_toi= true; - /* - Don't run in transaction mode with TOI actions. - */ - thd->variables.option_bits&= ~OPTION_BEGIN; - thd->server_status&= ~SERVER_STATUS_IN_TRANS; + wsrep_dump_rbr_buf_with_header(thd, buf, buf_len); } - wsrep_cb_status_t rcode(wsrep_apply_events(thd, buf, buf_len)); + + if (0 != rcode) + { + err.store(thd); + wsrep_rollback_common(thd, err); + } + else if (thd->wsrep_SR_thd && wsrep_SR_store) + { + /* remove trx from persistent storage on last fragment */ + if ((flags & WSREP_FLAG_TRX_END)) + { + WSREP_DEBUG("last fragment, cleanup SR table "); + DBUG_EXECUTE_IF("crash_apply_cb_before_fragment_removal", + DBUG_SUICIDE();); + SR_trx->cleanup(); + DBUG_EXECUTE_IF("crash_apply_cb_after_fragment_removal", + DBUG_SUICIDE();); + } + else + { + DBUG_EXECUTE_IF("crash_apply_cb_before_append_frag", + DBUG_SUICIDE();); + SR_trx->append_fragment(meta); + /* store the fragment in persistent storage */ + WSREP_DEBUG("append fragment to SR table"); + orig_thd->store_globals(); + wsrep_SR_store->append_frag_apply(orig_thd, + flags, + (const uchar*)buf, + buf_len); + thd->store_globals(); + DBUG_EXECUTE_IF("crash_apply_cb_after_append_frag", + DBUG_SUICIDE();); + } + } + + thd->close_temporary_tables(); + + if (SR_trx) + { + if (rcode) + { + WSREP_DEBUG("fragment trx destruction"); +//gcf487 trans_rollback(thd); - done in wsrep_rollback_common() +// close_thread_tables(thd); +// sr_pool->remove(orig_thd, thd, true); + } + wsrep_restore_applier_ctx(SR_trx, orig_thd); + } + DBUG_RETURN(rcode); +} + + +static int wsrep_apply_toi(THD* const thd, + const void* const buf, + size_t const buf_len, + uint32_t const flags, + const wsrep_trx_meta_t* const meta, + wsrep_apply_error& err) +{ + DBUG_ENTER("wsrep_apply_toi"); + + DBUG_ASSERT(flags & WSREP_FLAG_ISOLATION); + + + thd->wsrep_trx_meta = *meta; + + thd->wsrep_apply_toi= true; + + /* + Don't run in transaction mode with TOI actions. These will be + reset to defaults in commit callback. + */ + thd->variables.option_bits&= ~OPTION_BEGIN; + thd->server_status&= ~SERVER_STATUS_IN_TRANS; + + thd->store_globals(); + + int const rcode(wsrep_apply_events(thd, buf, buf_len)); + + if (0 != rcode || thd->wsrep_has_ignored_error) + { + wsrep_dump_rbr_buf_with_header(thd, buf, buf_len); + thd->wsrep_has_ignored_error= false; + + if (0 != rcode) err.store(thd); + } + + thd->close_temporary_tables(); + + DBUG_RETURN(rcode); +} + + +static void wsrep_apply_non_blocking(THD* thd, void* args) +{ + /* Go to BF mode */ + wsrep_thd_shadow shadow; + wsrep_prepare_bf_thd(thd, &shadow); + + Wsrep_nbo_ctx* nbo_ctx= (Wsrep_nbo_ctx*) args; + + DBUG_ASSERT(nbo_ctx); + + /* + Record context for synchronizing with applier thread once + MDL locks have been aquired. + */ + thd->wsrep_nbo_ctx= nbo_ctx; + + /* Must be applier thread */ + assert(thd->wsrep_exec_mode == REPL_RECV); + + /* Set OSU method for non blocking */ + thd->variables.wsrep_OSU_method= WSREP_OSU_NBO; + + /* + First apply TOI action as usual, wsrep->to_execute_start() will + be called at stmt commit. Applying is always assumed to succeed here. + Non-blocking operation end is supposed to sync the end result with + group and abort if the result does not match. + */ + wsrep_apply_error err; + if (wsrep_apply_toi(thd, nbo_ctx->buf(), nbo_ctx->buf_len(), nbo_ctx->flags(), + &nbo_ctx->meta(), err) != WSREP_CB_SUCCESS) + { + WSREP_DEBUG("Applying NBO failed"); + } + + /* + Applying did not cause action to signal slave thread. Wake up + the slave before exit. + */ + if (!thd->wsrep_nbo_ctx->ready()) thd->wsrep_nbo_ctx->signal(); + + /* Non-blocking operation end. No need to take action on error here, + it is handled by provider. */ + wsrep_buf_t const err_buf= err.get_buf(); + if (thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED && + wsrep->to_execute_end(wsrep, thd->thread_id, &err_buf) != WSREP_OK) + { + WSREP_WARN("Non-blocking operation end failed"); + } + + if (wsrep->free_connection(wsrep, thd->thread_id) != WSREP_OK) + { + WSREP_WARN("Failed to free connection: %llu", + (long long unsigned)thd->thread_id); + } + + thd->wsrep_nbo_ctx= NULL; + delete nbo_ctx; + + /* Return from BF mode before syncing with group */ + wsrep_return_from_bf_mode(thd, &shadow); +} + +static int start_nbo_thd(const void* const buf, + size_t const buf_len, + uint32_t const flags, + const wsrep_trx_meta_t* const meta) +{ + int rcode= WSREP_RET_SUCCESS; + + // Non-blocking operation start + Wsrep_nbo_ctx* nbo_ctx= 0; + Wsrep_thd_args* args= 0; + try + { + nbo_ctx= new Wsrep_nbo_ctx(buf, buf_len, flags, *meta); + args= new Wsrep_thd_args(wsrep_apply_non_blocking, nbo_ctx); + pthread_t th; + int err; + int max_tries= 1000; + while ((err= pthread_create(&th, &connection_attrib, start_wsrep_THD, + args)) == EAGAIN) + { + --max_tries; + if (max_tries == 0) + { + delete nbo_ctx; + delete args; + WSREP_ERROR("Failed to create thread for non-blocking operation: %d", + err); + return WSREP_ERR_FAILED; + } + else + { + usleep(1000); + } + } + + // Detach thread and wait until worker signals that it has locked + // required resources. + pthread_detach(th); + nbo_ctx->wait_sync(); + // nbo_ctx will be deleted by worker thread + } + catch (...) + { + delete nbo_ctx; + delete args; + WSREP_ERROR("Caught exception while trying to create thread for " + "non-blocking operation"); + rcode= WSREP_ERR_FAILED; + } + + return rcode; +} + +int wsrep_apply(void* const ctx, + uint32_t const flags, + const wsrep_buf_t* const buf, + const wsrep_trx_meta_t* meta, + wsrep_apply_error& err) +{ + THD* thd= (THD*)ctx; + + DBUG_ENTER("wsrep_apply"); + + DBUG_ASSERT(!WSREP_NBO_END(flags) || WSREP_FLAG_ROLLBACK & flags); + + thd->wsrep_trx_meta = *meta; #ifdef WSREP_PROC_INFO snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, - "Applied write set %lld", (long long)wsrep_thd_trx_seqno(thd)); + "applying write set %lld: %p, %zu", + (long long)wsrep_thd_trx_seqno(thd), buf->ptr, buf->len); thd_proc_info(thd, thd->wsrep_info); #else - thd_proc_info(thd, "Applied write set"); + thd_proc_info(thd, "Applying write set"); #endif /* WSREP_PROC_INFO */ - if (WSREP_CB_SUCCESS != rcode) + WSREP_DEBUG("apply_cb with flags: %u seqno: %ld, srctrx: %ld", + flags, meta->gtid.seqno, meta->stid.trx); + + bool const rollback(WSREP_FLAG_ROLLBACK & flags); + int rcode= 0; + + if (!(flags & WSREP_FLAG_ISOLATION)) { - wsrep_dump_rbr_buf_with_header(thd, buf, buf_len); + // Transaction + if (!rollback) + { + DBUG_ASSERT(meta->stid.trx != uint64_t(-1)); + rcode= wsrep_apply_trx(thd, buf->ptr, buf->len, flags, meta, err); + } + else + { + DBUG_ASSERT(meta->stid.trx != uint64_t(-1) || + (NULL == buf->ptr && 0 == buf->len)); + rcode= wsrep_rollback_trx(thd, buf->ptr, buf->len, flags, meta, err); + } + DBUG_ASSERT(rcode == 0 || !err.is_null()); + DBUG_ASSERT(err.is_null() || rcode != 0); } - - if (thd->has_thd_temporary_tables()) + else if (WSREP_NBO_START(flags)) + { + // NBO-start + if (!rollback) + rcode = start_nbo_thd(buf->ptr, buf->len, flags, meta); + else + { + WSREP_DEBUG("Failed NBO start, seqno: %lld", + (long long)wsrep_thd_trx_seqno(thd)); + rcode= wsrep_rollback_common(thd, err); + } + } + else if (WSREP_NBO_END(flags)) { - WSREP_DEBUG("Applier %lld has temporary tables. Closing them now..", - thd->thread_id); - thd->close_temporary_tables(); + // ineffective NBO-end - binlog something for it + assert(rollback); + rcode= wsrep_rollback_common(thd, err); + } + else + { + // Regular TOI + if (!rollback) + rcode= wsrep_apply_toi(thd, buf->ptr, buf->len, flags, meta, err); + else + rcode= wsrep_rollback_common(thd, err); } - return rcode; + +#ifdef WSREP_PROC_INFO + snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, + "Applied write set %lld", (long long)wsrep_thd_trx_seqno(thd)); + thd_proc_info(thd, thd->wsrep_info); +#else + thd_proc_info(thd, "Applied write set"); +#endif /* WSREP_PROC_INFO */ + WSREP_DEBUG("apply_cb done with rcode: %d", rcode); + + DBUG_RETURN(rcode != 0 ? rcode : err.length()); } -static wsrep_cb_status_t wsrep_commit(THD* const thd) +static wsrep_cb_status_t wsrep_commit_thd(THD* const thd, + bool fragment_not_trx_end, + const wsrep_apply_error& err) { #ifdef WSREP_PROC_INFO snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, @@ -299,9 +802,36 @@ static wsrep_cb_status_t wsrep_commit(THD* const thd) #else thd_proc_info(thd, "Committing"); #endif /* WSREP_PROC_INFO */ + DBUG_ENTER("wsrep_commit_thd"); + + wsrep_cb_status_t rcode= WSREP_CB_SUCCESS; + if (!opt_log_slave_updates && wsrep_before_commit(thd, true)) + rcode= WSREP_CB_FAILURE; + WSREP_DEBUG("applier commit_thd "); + + /* + This is needed because the applying of DDL, does not call for binlog log_and_order + MySQL version is different, where at the end of DDL applyin, trans_commit_stmt has + a call for tc_log:commit(), and DDL binlogging happens there. + */ + if (opt_log_slave_updates && thd->wsrep_apply_toi && wsrep_before_commit(thd, true)) + { + rcode= WSREP_CB_FAILURE; + } + /* + We can ignore the storage engine durability setting for fragments + here: Committing a fragment does not cause actual transaction to + be committed, so it will be enough that the fragment is + committed in order to be able to recover to consistent state. + */ + + enum durability_properties dur_save= thd->durability_property; + if (fragment_not_trx_end) + thd->durability_property= HA_IGNORE_DURABILITY; - wsrep_cb_status_t const rcode(trans_commit(thd) ? - WSREP_CB_FAILURE : WSREP_CB_SUCCESS); + if (rcode == WSREP_CB_SUCCESS && trans_commit(thd)) + rcode= WSREP_CB_FAILURE; + thd->durability_property= dur_save; if (WSREP_CB_SUCCESS == rcode) { @@ -314,6 +844,30 @@ static wsrep_cb_status_t wsrep_commit(THD* const thd) wsrep_set_SE_checkpoint(thd->wsrep_trx_meta.gtid.uuid, thd->wsrep_trx_meta.gtid.seqno); } + if ((!opt_log_slave_updates || thd->wsrep_apply_toi) + && wsrep_ordered_commit(thd, true, err)) + rcode= WSREP_CB_FAILURE; + + if (rcode == WSREP_CB_SUCCESS) + { + DBUG_ASSERT(fragment_not_trx_end || + thd->wsrep_query_state_unsafe() == QUERY_ORDERED_COMMIT); + /* + FIXME: For some reason fragment commits don't go through + binlog commit group commit if log slave updates is on. This + effectively disables binlog group commit for dummy events + which are logged into binlog. + */ + if (fragment_not_trx_end && opt_log_slave_updates && !wsrep_gtid_mode) + { + if (wsrep_before_commit(thd, true) || + wsrep_ordered_commit(thd, true, err)) + { + WSREP_DEBUG("Binlog commit failed (WCT)"); + rcode= WSREP_CB_FAILURE; + } + } + } } #ifdef WSREP_PROC_INFO @@ -324,59 +878,117 @@ static wsrep_cb_status_t wsrep_commit(THD* const thd) thd_proc_info(thd, "Committed"); #endif /* WSREP_PROC_INFO */ - return rcode; + DBUG_RETURN(rcode); } -static wsrep_cb_status_t wsrep_rollback(THD* const thd) +static +wsrep_cb_status_t wsrep_commit(void* const ctx, + uint32_t const flags, + const wsrep_trx_meta_t* meta, + wsrep_bool_t* const exit, + const wsrep_apply_error& err) { -#ifdef WSREP_PROC_INFO - snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, - "Rolling back %lld", (long long)wsrep_thd_trx_seqno(thd)); - thd_proc_info(thd, thd->wsrep_info); -#else - thd_proc_info(thd, "Rolling back"); -#endif /* WSREP_PROC_INFO */ + DBUG_ENTER("wsrep_commit"); + WSREP_DEBUG("applier commit with flags: %u seqno: %ld, srctrx: %ld", + flags, meta->gtid.seqno, meta->stid.trx); - wsrep_cb_status_t const rcode(trans_rollback(thd) ? - WSREP_CB_FAILURE : WSREP_CB_SUCCESS); + THD* thd((THD*)ctx); + wsrep_cb_status_t rcode= WSREP_CB_SUCCESS; + bool const trx_end(flags & (WSREP_FLAG_TRX_END | WSREP_FLAG_ROLLBACK)); -#ifdef WSREP_PROC_INFO - snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, - "Rolled back %lld", (long long)wsrep_thd_trx_seqno(thd)); - thd_proc_info(thd, thd->wsrep_info); -#else - thd_proc_info(thd, "Rolled back"); -#endif /* WSREP_PROC_INFO */ + if (WSREP_NBO_START(flags)) + { + WSREP_DEBUG("NBO"); + wsrep_cb_status_t ret= WSREP_CB_SUCCESS; + if (wsrep_before_commit(thd, true) || + wsrep_ordered_commit(thd, true, err)) + { + ret= WSREP_CB_FAILURE; + } + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_EXEC); + thd->set_wsrep_query_state(QUERY_IDLE); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + DBUG_RETURN(ret); + } - return rcode; -} + bool const toi(flags & WSREP_FLAG_ISOLATION); // ineffective NBO end + bool const fragment(!((flags & WSREP_FLAG_TRX_START) && trx_end) && !toi); + wsrep_SR_trx_info* const SR_trx + (fragment ? sr_pool->find(meta->stid.node, meta->stid.trx) : NULL); -wsrep_cb_status_t wsrep_commit_cb(void* const ctx, - uint32_t const flags, - const wsrep_trx_meta_t* meta, - wsrep_bool_t* const exit, - bool const commit) -{ - THD* const thd((THD*)ctx); + if (!SR_trx && trx_end && fragment) + { + WSREP_DEBUG("SR trxid %ld seqno %lld has been aborted already, skipping " + "commit_cb", meta->stid.trx, (long long)meta->gtid.seqno); + } + else + { + assert(0 == SR_trx || fragment); + assert(!fragment || 0 != SR_trx); + } - assert(meta->gtid.seqno == wsrep_thd_trx_seqno(thd)); + if (SR_trx && trx_end) + { + void* opaque= thd->wsrep_ws_handle.opaque; + thd = SR_trx->get_THD(); + WSREP_DEBUG("last trx fragment, switching context from %p to %p", ctx, thd); + thd->wsrep_ws_handle.opaque= opaque; + thd->store_globals(); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_EXEC); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + DBUG_EXECUTE_IF("crash_commit_cb_before_last_fragment_commit", + DBUG_SUICIDE();); + } - wsrep_cb_status_t rcode; + thd->wsrep_trx_meta = *meta; + wsrep_xid_init(&thd->wsrep_xid, meta->gtid.uuid, meta->gtid.seqno); + assert(meta->gtid.seqno == wsrep_thd_trx_seqno(thd)); - if (commit) - rcode = wsrep_commit(thd); + /* + Failed certification, write a dummy binlog event in wsrep_gtid_mode + to keep GTID sequence continuous. If wsrep_gtid_mode is off, release + commit critical section. + */ + if (!fragment && (flags & WSREP_FLAG_ROLLBACK)) + { + if (wsrep_gtid_mode) + { + wsrep_write_dummy_event(thd, "rollback"); + } + else + { + if (wsrep_before_commit(thd, true) || + wsrep_ordered_commit(thd, true, err)) + { + WSREP_DEBUG("Binlog commit failed (WC)"); + rcode= WSREP_CB_FAILURE; + } + } + } else - rcode = wsrep_rollback(thd); + { + /* here if thd == SR_trx->get_thd() we are committing in SR context - + * that is SR transaction. + * otherwise we are committing in the usual applier context - + * that is regular transaction or SR fragment. */ + rcode = wsrep_commit_thd(thd, fragment && !trx_end, err); + } + + thd->wsrep_ws_handle.opaque= NULL; + thd->wsrep_xid.null(); - /* Cleanup */ wsrep_set_apply_format(thd, NULL); thd->mdl_context.release_transactional_locks(); thd->reset_query(); /* Mutex protected */ free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation; - if (wsrep_slave_count_change < 0 && commit && WSREP_CB_SUCCESS == rcode) + if (wsrep_slave_count_change < 0 && trx_end && WSREP_CB_SUCCESS == rcode) { + WSREP_DEBUG("applier commit, locking LOCK_wsrep_slave_threads %lu", thd->thread_id); + mysql_mutex_assert_not_owner(&LOCK_wsrep_thd_pool); mysql_mutex_lock(&LOCK_wsrep_slave_threads); if (wsrep_slave_count_change < 0) { @@ -394,13 +1006,85 @@ wsrep_cb_status_t wsrep_commit_cb(void* const ctx, thd->wsrep_apply_toi= false; } - return rcode; + /* Cleanup for streaming replication */ + if (SR_trx && trx_end) + { + SR_trx->release(); + + /* Cleanup for streaming replication */ + if (trx_end) + { + sr_pool->remove((THD*)ctx, meta->stid.node, meta->stid.trx, false); + DBUG_EXECUTE_IF("crash_commit_cb_last_fragment_commit_success", + DBUG_SUICIDE();); + /* Set thd to null as it is deleted in sr_pool->remove() */ + thd= NULL; + } + } + + if (thd) + { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_EXEC); + if (thd->wsrep_conflict_state() != REPLAYING) + { + thd->set_wsrep_query_state(QUERY_IDLE); + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } + if (ctx != thd) + { + thd= (THD*)ctx; + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state() != REPLAYING) + { + thd->set_wsrep_query_state(QUERY_IDLE); + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } + + DBUG_RETURN(rcode); } +wsrep_cb_status_t wsrep_apply_cb(void* const ctx, + const wsrep_ws_handle_t* ws_handle, + uint32_t flags, + const wsrep_buf_t* const buf, + const wsrep_trx_meta_t* meta, + wsrep_bool_t* exit_loop) +{ + assert(meta->gtid.seqno > 0); + DBUG_ENTER("wsrep_apply_cb"); + + THD *thd= (THD*)ctx; + void* opaque_save= thd->wsrep_ws_handle.opaque; + thd->wsrep_ws_handle.opaque= ws_handle->opaque; + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state() != REPLAYING) + thd->set_wsrep_query_state(QUERY_EXEC); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + wsrep_apply_error err; + int const apply_err= wsrep_apply(ctx, flags, buf, meta, err); + DBUG_ASSERT(0 == apply_err || !err.is_null()); + DBUG_ASSERT(0 != apply_err || err.is_null()); + + if (0 != apply_err) flags |= WSREP_FLAG_ROLLBACK; + + wsrep_cb_status_t rcode= wsrep_commit(ctx, flags, meta, exit_loop, err); + + thd->wsrep_ws_handle.opaque= opaque_save; + + DBUG_ASSERT(thd->wsrep_conflict_state_unsafe() == REPLAYING || + thd->wsrep_query_state_unsafe() == QUERY_IDLE); + + DBUG_RETURN(rcode); +} -wsrep_cb_status_t wsrep_unordered_cb(void* const ctx, - const void* const data, - size_t const size) +wsrep_cb_status_t wsrep_unordered_cb(void* const ctx, + const wsrep_buf_t* const data) { return WSREP_CB_SUCCESS; } + diff --git a/sql/wsrep_applier.h b/sql/wsrep_applier.h index f19d2d46d0c..a64c0e5eb12 100644 --- a/sql/wsrep_applier.h +++ b/sql/wsrep_applier.h @@ -1,4 +1,4 @@ -/* Copyright 2013 Codership Oy <http://www.codership.com> +/* Copyright 2013-2015 Codership Oy <http://www.codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,26 +19,63 @@ #include <my_config.h> #include "../wsrep/wsrep_api.h" +#include "sql_class.h" // THD class + void wsrep_set_apply_format(THD* thd, Format_description_log_event* ev); Format_description_log_event* wsrep_get_apply_format(THD* thd); +int wsrep_apply_events(THD* thd, + const void* events_buf, + size_t buf_len); + /* wsrep callback prototypes */ -extern "C" { -wsrep_cb_status_t wsrep_apply_cb(void *ctx, - const void* buf, size_t buf_len, - uint32_t flags, - const wsrep_trx_meta_t* meta); +wsrep_cb_status_t wsrep_apply_cb(void* ctx, + const wsrep_ws_handle_t* ws_handle, + uint32_t flags, + const wsrep_buf_t* buf, + const wsrep_trx_meta_t* meta, + wsrep_bool_t* exit_loop); + +/* Applier error codes, when nothing better is available. */ +#define WSREP_RET_SUCCESS 0 // Success +#define WSREP_ERR_GENERIC 1 // When in doubt (MySQL default error code) +#define WSREP_ERR_BAD_EVENT 2 // Can't parse event +#define WSREP_ERR_NOT_FOUND 3 // Key. table, schema not found +#define WSREP_ERR_EXISTS 4 // Key, table, schema already exists +#define WSREP_ERR_WRONG_TYPE 5 // Incompatible data type +#define WSREP_ERR_FAILED 6 // Operation failed for some internal reason +#define WSREP_ERR_ABORTED 7 // Operation was aborted externally + +class wsrep_apply_error +{ +public: + wsrep_apply_error() : str_(NULL), len_(0) {}; + ~wsrep_apply_error() { ::free(str_); } + /* stores the current THD error info from the diagnostic area. Works only + * once, subsequent invocations are ignored in order to preserve the original + * condition. */ + void store(const THD* thd); + const char* c_str() const { return str_; } + size_t length() const { return len_; } + bool is_null() const { return (c_str() == NULL && length() == 0); } + wsrep_buf_t get_buf() const + { + wsrep_buf_t ret= { c_str(), length() }; + return ret; + } +private: + char* str_; + size_t len_; +}; -wsrep_cb_status_t wsrep_commit_cb(void *ctx, - uint32_t flags, - const wsrep_trx_meta_t* meta, - wsrep_bool_t* exit, - bool commit); +int wsrep_apply(void* ctx, + uint32_t flags, + const wsrep_buf_t* buf, + const wsrep_trx_meta_t* meta, + wsrep_apply_error& err); -wsrep_cb_status_t wsrep_unordered_cb(void* ctx, - const void* data, - size_t size); +wsrep_cb_status_t wsrep_unordered_cb(void* ctx, + const wsrep_buf_t* data); -} /* extern "C" */ #endif /* WSREP_APPLIER_H */ diff --git a/sql/wsrep_binlog.cc b/sql/wsrep_binlog.cc index cafd41b2653..66e743d6472 100644 --- a/sql/wsrep_binlog.cc +++ b/sql/wsrep_binlog.cc @@ -20,6 +20,12 @@ #include "log_event.h" #include "wsrep_applier.h" +#include "transaction.h" + +const char *wsrep_fragment_units[] = { "bytes", "events", "rows", "statements", NullS }; +const char *wsrep_SR_store_types[] = { "none", "file", "table", NullS }; + + extern handlerton *binlog_hton; /* Write the contents of a cache to a memory buffer. @@ -112,7 +118,7 @@ heap_size(size_t length) } /* append data to writeset */ -static inline wsrep_status_t +static inline wsrep_trx_status wsrep_append_data(wsrep_t* const wsrep, wsrep_ws_handle_t* const ws, const void* const data, @@ -125,9 +131,13 @@ wsrep_append_data(wsrep_t* const wsrep, if (rc != WSREP_OK) { WSREP_WARN("append_data() returned %d", rc); + if (WSREP_SIZE_EXCEEDED == rc) + return WSREP_TRX_SIZE_EXCEEDED; + else + return WSREP_TRX_ERROR; } - return rc; + return WSREP_TRX_OK; } /* @@ -139,29 +149,33 @@ wsrep_append_data(wsrep_t* const wsrep, This version reads all of cache into single buffer and then appends to a writeset at once. */ -static int wsrep_write_cache_once(wsrep_t* const wsrep, - THD* const thd, - IO_CACHE* const cache, - size_t* const len) +static wsrep_trx_status wsrep_write_cache_once(wsrep_t* const wsrep, + THD* const thd, + IO_CACHE* const cache, + size_t* const len) { my_off_t const saved_pos(my_b_tell(cache)); DBUG_ENTER("wsrep_write_cache_once"); - if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0)) + if (reinit_io_cache(cache, READ_CACHE, wsrep_get_fragment_base(thd), 0, 0)) { WSREP_ERROR("failed to initialize io-cache"); - DBUG_RETURN(ER_ERROR_ON_WRITE); + DBUG_RETURN(WSREP_TRX_ERROR); } - int err(WSREP_OK); + wsrep_trx_status ret(WSREP_TRX_OK); size_t total_length(0); uchar stack_buf[STACK_SIZE]; /* to avoid dynamic allocations for few data*/ - uchar* heap_buf(NULL); uchar* buf(stack_buf); size_t allocated(sizeof(stack_buf)); size_t used(0); + if (thd->wsrep_fragments_sent > 0) + { + allocated = 0; + } + uint length(my_b_bytes_in_cache(cache)); if (unlikely(0 == length)) length = my_b_fill(cache); @@ -178,31 +192,31 @@ static int wsrep_write_cache_once(wsrep_t* const wsrep, { WSREP_WARN("transaction size limit (%lu) exceeded: %zu", wsrep_max_ws_size, total_length); - err = WSREP_TRX_SIZE_EXCEEDED; + ret = WSREP_TRX_SIZE_EXCEEDED; goto cleanup; } if (total_length > allocated) { size_t const new_size(heap_size(total_length)); - uchar* tmp = (uchar *)my_realloc(heap_buf, new_size, - MYF(MY_ALLOW_ZERO_PTR)); + uchar* tmp = (uchar *)my_realloc(thd->wsrep_rbr_buf, + new_size, MYF(MY_ALLOW_ZERO_PTR)); if (!tmp) { WSREP_ERROR("could not (re)allocate buffer: %zu + %u", allocated, length); - err = WSREP_TRX_SIZE_EXCEEDED; + ret = WSREP_TRX_ERROR; goto cleanup; } - heap_buf = tmp; - buf = heap_buf; + thd->wsrep_rbr_buf = tmp; + buf = thd->wsrep_rbr_buf; allocated = new_size; if (used <= STACK_SIZE && used > 0) // there's data in stack_buf { DBUG_ASSERT(buf == stack_buf); - memcpy(heap_buf, stack_buf, used); + memcpy(thd->wsrep_rbr_buf, stack_buf, used); } } @@ -216,23 +230,34 @@ static int wsrep_write_cache_once(wsrep_t* const wsrep, } while ((length = my_b_fill(cache))); if (used > 0) - err = wsrep_append_data(wsrep, &thd->wsrep_ws_handle, buf, used); + ret = wsrep_append_data(wsrep, &thd->wsrep_ws_handle, buf, used); - if (WSREP_OK == err) *len = total_length; + if (WSREP_TRX_OK == ret) + { +#ifndef NDEBUG + ulong fb= wsrep_get_fragment_base(thd); + assert(total_length + fb == saved_pos); +#endif + } cleanup: + *len = total_length; if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0)) { WSREP_ERROR("failed to reinitialize io-cache"); } - if (unlikely(WSREP_OK != err)) + if (unlikely(WSREP_TRX_OK != ret)) { wsrep_dump_rbr_buf_with_header(thd, buf, used); } + if (thd->wsrep_fragments_sent == 0) + { + my_free(thd->wsrep_rbr_buf); + thd->wsrep_rbr_buf = NULL; + } - my_free(heap_buf); - DBUG_RETURN(err); + DBUG_RETURN(ret); } /* @@ -243,21 +268,21 @@ cleanup: This version uses incremental data appending as it reads it from cache. */ -static int wsrep_write_cache_inc(wsrep_t* const wsrep, - THD* const thd, - IO_CACHE* const cache, - size_t* const len) +static wsrep_trx_status wsrep_write_cache_inc(wsrep_t* const wsrep, + THD* const thd, + IO_CACHE* const cache, + size_t* const len) { my_off_t const saved_pos(my_b_tell(cache)); DBUG_ENTER("wsrep_write_cache_inc"); - if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0)) + if (reinit_io_cache(cache, READ_CACHE, wsrep_get_fragment_base(thd), 0, 0)) { WSREP_ERROR("failed to initialize io-cache"); DBUG_RETURN(WSREP_TRX_ERROR); } - int err(WSREP_OK); + wsrep_trx_status ret(WSREP_TRX_OK); size_t total_length(0); @@ -275,12 +300,12 @@ static int wsrep_write_cache_inc(wsrep_t* const wsrep, { WSREP_WARN("transaction size limit (%lu) exceeded: %zu", wsrep_max_ws_size, total_length); - err = WSREP_TRX_SIZE_EXCEEDED; + ret = WSREP_TRX_SIZE_EXCEEDED; goto cleanup; } - if(WSREP_OK != (err=wsrep_append_data(wsrep, &thd->wsrep_ws_handle, - cache->read_pos, length))) + if(WSREP_TRX_OK != (ret=wsrep_append_data(wsrep, &thd->wsrep_ws_handle, + cache->read_pos, length))) goto cleanup; if (cache->file < 0) @@ -290,15 +315,19 @@ static int wsrep_write_cache_inc(wsrep_t* const wsrep, } } while ((length = my_b_fill(cache))); - if (WSREP_OK == err) *len = total_length; + if (WSREP_TRX_OK == ret) + { + assert(total_length + wsrep_get_fragment_base(thd) == saved_pos); + } cleanup: + *len = total_length; if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0)) { WSREP_ERROR("failed to reinitialize io-cache"); } - DBUG_RETURN(err); + DBUG_RETURN(ret); } /* @@ -307,12 +336,12 @@ cleanup: This function quite the same as MYSQL_BIN_LOG::write_cache(), with the exception that here we write in buffer instead of log file. */ -int wsrep_write_cache(wsrep_t* const wsrep, - THD* const thd, - IO_CACHE* const cache, - size_t* const len) +wsrep_trx_status wsrep_write_cache(wsrep_t* const wsrep, + THD* const thd, + IO_CACHE* const cache, + size_t* const len) { - if (wsrep_incremental_data_collection) { + if (wsrep_incremental_data_collection && thd->wsrep_fragments_sent == 0) { return wsrep_write_cache_inc(wsrep, thd, cache, len); } else { @@ -512,3 +541,99 @@ cleanup1: DBUG_VOID_RETURN; } +#include "wsrep_thd_pool.h" +extern Wsrep_thd_pool *wsrep_thd_pool; + +#include "log_event.h" +// #include "binlog.h" + +int wsrep_write_dummy_event_low(THD *thd, const char *msg) +{ + int ret= 0; + if (mysql_bin_log.is_open() && wsrep_gtid_mode) + { + DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED); + + /* For restoring orig thd state before returing it back to pool */ + int wsrep_on= thd->variables.wsrep_on; + int sql_log_bin= thd->variables.sql_log_bin; + int option_bits= thd->variables.option_bits; + enum wsrep_exec_mode exec_mode= thd->wsrep_exec_mode; + + /* + Fake that the connection is local client connection for the duration + of mysql_bin_log.write_event(), otherwise the write will fail. + */ + thd->wsrep_exec_mode= LOCAL_STATE; + thd->variables.wsrep_on= 1; + thd->variables.sql_log_bin= 1; + thd->variables.option_bits |= OPTION_BIN_LOG; + + Ignorable_log_event skip_event(thd); + ret= mysql_bin_log.write_event(&skip_event); + + /* Restore original thd state */ + thd->wsrep_exec_mode= exec_mode; + thd->variables.wsrep_on= wsrep_on; + thd->variables.sql_log_bin= sql_log_bin; + thd->variables.option_bits= option_bits; + + if (ret) + { + WSREP_ERROR("Write to binlog failed: %d", ret); + abort(); + unireg_abort(1); + } + ret= trans_commit_stmt(thd); + if (ret) + { + WSREP_ERROR("STMT commit failed: %d", ret); + abort(); + } + } + + return ret; +} + +int wsrep_write_dummy_event(THD *orig_thd, const char *msg) +{ + if (WSREP_EMULATE_BINLOG(orig_thd)) + { + return 0; + } + + /* Use tmp thd for the transaction to avoid messing up orig_thd + transaction state */ + THD* thd= wsrep_thd_pool->get_thd(0); + + if (!thd) + { + return 1; + } + + /* + Use original THD wsrep TRX meta data and WS handle to make + commit generate GTID and go through commit ordering hooks. + */ + wsrep_trx_meta_t meta_save= thd->wsrep_trx_meta; + thd->wsrep_trx_meta= orig_thd->wsrep_trx_meta; + wsrep_ws_handle_t handle_save= thd->wsrep_ws_handle; + thd->wsrep_ws_handle= orig_thd->wsrep_ws_handle; + + int ret= wsrep_write_dummy_event_low(thd, msg); + + if (ret || (ret= trans_commit(thd))) + { + WSREP_ERROR("Failed to write skip event into binlog"); + abort(); + unireg_abort(1); + } + + thd->wsrep_trx_meta= meta_save; + thd->wsrep_ws_handle= handle_save; + + wsrep_thd_pool->release_thd(thd); + + orig_thd->store_globals(); + return ret; +} diff --git a/sql/wsrep_binlog.h b/sql/wsrep_binlog.h index 864813d5c98..8c7f124fcbd 100644 --- a/sql/wsrep_binlog.h +++ b/sql/wsrep_binlog.h @@ -16,11 +16,38 @@ #ifndef WSREP_BINLOG_H #define WSREP_BINLOG_H +#include "my_global.h" + +#define WSREP_FRAG_BYTES 0 +#define WSREP_FRAG_EVENTS 1 +#define WSREP_FRAG_ROWS 2 +#define WSREP_FRAG_STATEMENTS 3 + +#define WSREP_SR_STORE_NONE 0 +#define WSREP_SR_STORE_FILE 1 +#define WSREP_SR_STORE_TABLE 2 + +extern ulong wsrep_SR_store_type; +extern const char *wsrep_fragment_units[]; +extern const char *wsrep_SR_store_types[]; + +class wsrep_SR_trx; #include "sql_class.h" // THD, IO_CACHE #define HEAP_PAGE_SIZE 65536 /* 64K */ #define WSREP_MAX_WS_SIZE 2147483647 /* 2GB */ +bool wsrep_fragment_full(THD *thd); +void wsrep_reset_SR_trans(THD *thd); +void wsrep_reset_SR_fill(THD *thd); +int wsrep_append_SR_trans(THD *thd, ulong unit, ulong size, bool replicate); +bool wsrep_fragmented(THD *thd); +void wsrep_step_fragment_base(THD *thd, ulong size); +ulong wsrep_get_fragment_base(THD *thd); +void wsrep_append_fill_rate(THD*, ulong); +void wsrep_reset_fragment_fill(THD*, ulong); +ulong wsrep_get_fragment_fill(THD*); + /* Write the contents of a cache to a memory buffer. @@ -38,23 +65,33 @@ int wsrep_write_cache_buf(IO_CACHE *cache, uchar **buf, size_t *buf_len); @param len total amount of data written @return wsrep error status */ -int wsrep_write_cache (wsrep_t* const wsrep, - THD* const thd, - IO_CACHE* const cache, - size_t* const len); +wsrep_trx_status wsrep_write_cache(wsrep_t* wsrep, + THD* thd, + IO_CACHE* cache, + size_t* len); /* Dump replication buffer to disk */ void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len); -/* Dump replication buffer to disk without intermediate buffer */ -void wsrep_dump_rbr_direct(THD* thd, IO_CACHE* cache); - /* Dump replication buffer along with header to a file */ void wsrep_dump_rbr_buf_with_header(THD *thd, const void *rbr_buf, size_t buf_len); int wsrep_binlog_close_connection(THD* thd); -int wsrep_binlog_savepoint_set(THD *thd, void *sv); -int wsrep_binlog_savepoint_rollback(THD *thd, void *sv); +uint wsrep_get_trans_cache_position(THD *thd); + +/* + Write dummy event into binlog in place of unused GTID. + The binlog write is done in thd context. +*/ +int wsrep_write_dummy_event_low(THD *thd, const char *msg); +/* + Write dummy event to binlog in place of unused GTID and + commit. The binlog write and commit are done in temporary + thd context, the original thd state is not altered. +*/ +int wsrep_write_dummy_event(THD* thd, const char *msg); + +void wsrep_register_binlog_handler(THD *thd, bool trx); #endif /* WSREP_BINLOG_H */ diff --git a/sql/wsrep_dummy.cc b/sql/wsrep_dummy.cc index 0b6e7e0d5bb..57cc0d51997 100644 --- a/sql/wsrep_dummy.cc +++ b/sql/wsrep_dummy.cc @@ -17,7 +17,13 @@ #include <sql_class.h> #include <mysql/service_wsrep.h> -my_bool wsrep_thd_is_BF(THD *, my_bool) +int64_t wsrep_thd_trx_seqno(const THD *) +{ return 0;} + +my_thread_id wsrep_thd_thread_id(THD *thd) +{ return (my_thread_id)0; } + +my_bool wsrep_thd_is_BF(void *, my_bool) { return 0; } int wsrep_trx_order_before(THD *, THD *) @@ -26,7 +32,8 @@ int wsrep_trx_order_before(THD *, THD *) enum wsrep_conflict_state wsrep_thd_conflict_state(THD *, my_bool) { return NO_CONFLICT; } -int wsrep_is_wsrep_xid(const XID*) +//int wsrep_is_wsrep_xid(const XID*) +int wsrep_is_wsrep_xid(const void* xid) { return 0; } long long wsrep_xid_seqno(const XID* x) @@ -38,10 +45,13 @@ const unsigned char* wsrep_xid_uuid(const XID*) return uuid; } +bool wsrep_prepare_key_for_innodb(THD* thd, const uchar*, size_t, const uchar*, size_t, struct wsrep_buf*, size_t*) +{ return 0; } + bool wsrep_prepare_key(const uchar*, size_t, const uchar*, size_t, struct wsrep_buf*, size_t*) { return 0; } -struct wsrep *get_wsrep() +struct wsrep_st *get_wsrep() { return 0; } my_bool get_wsrep_certify_nonPK() @@ -77,6 +87,9 @@ bool wsrep_consistency_check(THD *) void wsrep_lock_rollback() { } +int wsrep_on(void *) +{ return 0;} + int wsrep_on(THD *thd) { return 0; } diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index d4d35d752be..79072bb1916 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -340,6 +340,7 @@ wsrep_run_wsrep_commit(THD *thd, bool all) thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message()); } + DBUG_ENTER("wsrep_run_wsrep_commit"); DEBUG_SYNC(thd, "wsrep_before_replication"); if (thd->slave_thread && !opt_log_slave_updates) DBUG_RETURN(WSREP_TRX_OK); diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 0a2735fe0b7..951497e100f 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -13,8 +13,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#include "sql_plugin.h" /* wsrep_plugins_pre_init() */ +#include <sql_plugin.h> // SHOW_MY_BOOL +#include "mariadb.h" #include <mysqld.h> +#include <transaction.h> #include <sql_class.h> #include <sql_parse.h> #include <sql_base.h> /* find_temporary_table() */ @@ -33,9 +35,16 @@ #include "wsrep_var.h" #include "wsrep_binlog.h" #include "wsrep_applier.h" +#include "wsrep_sr.h" +#include "wsrep_sr_file.h" +#include "wsrep_sr_table.h" +#include "wsrep_schema.h" +#include "wsrep_thd_pool.h" #include "wsrep_xid.h" +#include "wsrep_trans_observer.h" #include <cstdio> #include <cstdlib> +#include <string> #include "log_event.h" #include <slave.h> @@ -85,7 +94,7 @@ my_bool wsrep_certify_nonPK; // Certify, even when no primary my_bool wsrep_recovery; // Recovery my_bool wsrep_replicate_myisam; // Enable MyISAM replication my_bool wsrep_log_conflicts; -my_bool wsrep_load_data_splitting; // Commit load data every 10K intervals +my_bool wsrep_load_data_splitting= 0; // Commit load data every 10K intervals my_bool wsrep_slave_UK_checks; // Slave thread does UK checks my_bool wsrep_slave_FK_checks; // Slave thread does FK checks my_bool wsrep_sst_donor_rejects_queries; @@ -111,7 +120,15 @@ my_bool wsrep_restart_slave_activated= 0; // Node has dropped, and slave bool wsrep_new_cluster= false; // Bootstrap the cluster? int wsrep_slave_count_change= 0; // No. of appliers to stop/start int wsrep_to_isolation= 0; // No. of active TO isolation threads -long wsrep_max_protocol_version= 3; // Maximum protocol version to use +long wsrep_max_protocol_version= 4; // Maximum protocol version to use +long int wsrep_protocol_version= wsrep_max_protocol_version; +ulong wsrep_trx_fragment_size= 0; // size limit for fragmenting + // 0 = no fragmenting +ulong wsrep_trx_fragment_unit= WSREP_FRAG_BYTES; + // unit for fragment size +ulong wsrep_SR_store_type= WSREP_SR_STORE_TABLE; +uint wsrep_ignore_apply_errors= 0; + /* * End configuration options @@ -127,29 +144,36 @@ mysql_mutex_t LOCK_wsrep_sst; mysql_cond_t COND_wsrep_sst; mysql_mutex_t LOCK_wsrep_sst_init; mysql_cond_t COND_wsrep_sst_init; -mysql_mutex_t LOCK_wsrep_rollback; -mysql_cond_t COND_wsrep_rollback; -wsrep_aborting_thd_t wsrep_aborting_thd= NULL; mysql_mutex_t LOCK_wsrep_replaying; mysql_cond_t COND_wsrep_replaying; mysql_mutex_t LOCK_wsrep_slave_threads; mysql_mutex_t LOCK_wsrep_desync; mysql_mutex_t LOCK_wsrep_config_state; +mysql_mutex_t LOCK_wsrep_SR_pool; +mysql_mutex_t LOCK_wsrep_SR_store; +mysql_mutex_t LOCK_wsrep_thd_pool; /* locking policy: + 1. LOCK_wsrep_slave_threads + 2. LOCK_wsrep_thd_pool + */ int wsrep_replaying= 0; ulong wsrep_running_threads = 0; // # of currently running wsrep threads ulong my_bind_addr; #ifdef HAVE_PSI_INTERFACE -PSI_mutex_key key_LOCK_wsrep_rollback, +PSI_mutex_key key_LOCK_wsrep_thd, key_LOCK_wsrep_replaying, key_LOCK_wsrep_ready, key_LOCK_wsrep_sst, key_LOCK_wsrep_sst_thread, key_LOCK_wsrep_sst_init, key_LOCK_wsrep_slave_threads, key_LOCK_wsrep_desync, - key_LOCK_wsrep_config_state; + key_LOCK_wsrep_config_state, + key_LOCK_wsrep_SR_pool, + key_LOCK_wsrep_SR_store, key_LOCK_wsrep_thd_pool, key_LOCK_wsrep_nbo, + key_LOCK_wsrep_thd_queue; -PSI_cond_key key_COND_wsrep_rollback, +PSI_cond_key key_COND_wsrep_thd, key_COND_wsrep_replaying, key_COND_wsrep_ready, key_COND_wsrep_sst, - key_COND_wsrep_sst_init, key_COND_wsrep_sst_thread; + key_COND_wsrep_sst_init, key_COND_wsrep_sst_thread, + key_COND_wsrep_nbo, key_COND_wsrep_thd_queue; PSI_file_key key_file_wsrep_gra_log; @@ -160,20 +184,23 @@ static PSI_mutex_info wsrep_mutexes[]= { &key_LOCK_wsrep_sst_thread, "wsrep_sst_thread", 0}, { &key_LOCK_wsrep_sst_init, "LOCK_wsrep_sst_init", PSI_FLAG_GLOBAL}, { &key_LOCK_wsrep_sst, "LOCK_wsrep_sst", PSI_FLAG_GLOBAL}, - { &key_LOCK_wsrep_rollback, "LOCK_wsrep_rollback", PSI_FLAG_GLOBAL}, + { &key_LOCK_wsrep_thd, "THD::LOCK_wsrep_thd", 0}, { &key_LOCK_wsrep_replaying, "LOCK_wsrep_replaying", PSI_FLAG_GLOBAL}, { &key_LOCK_wsrep_slave_threads, "LOCK_wsrep_slave_threads", PSI_FLAG_GLOBAL}, { &key_LOCK_wsrep_desync, "LOCK_wsrep_desync", PSI_FLAG_GLOBAL}, - { &key_LOCK_wsrep_config_state, "LOCK_wsrep_config_state", PSI_FLAG_GLOBAL} + { &key_LOCK_wsrep_config_state, "LOCK_wsrep_config_state", PSI_FLAG_GLOBAL}, + { &key_LOCK_wsrep_SR_pool, "LOCK_wsrep_SR_pool", PSI_FLAG_GLOBAL}, + { &key_LOCK_wsrep_SR_store, "LOCK_wsrep_SR_store", PSI_FLAG_GLOBAL}, + { &key_LOCK_wsrep_thd_pool, "LOCK_wsrep_thd_pool", PSI_FLAG_GLOBAL} }; static PSI_cond_info wsrep_conds[]= { + { &key_COND_wsrep_thd, "COND_wsrep_thd", PSI_FLAG_GLOBAL}, { &key_COND_wsrep_ready, "COND_wsrep_ready", PSI_FLAG_GLOBAL}, { &key_COND_wsrep_sst, "COND_wsrep_sst", PSI_FLAG_GLOBAL}, { &key_COND_wsrep_sst_init, "COND_wsrep_sst_init", PSI_FLAG_GLOBAL}, { &key_COND_wsrep_sst_thread, "wsrep_sst_thread", 0}, - { &key_COND_wsrep_rollback, "COND_wsrep_rollback", PSI_FLAG_GLOBAL}, { &key_COND_wsrep_replaying, "COND_wsrep_replaying", PSI_FLAG_GLOBAL} }; @@ -185,6 +212,7 @@ static PSI_file_info wsrep_files[]= my_bool wsrep_inited = 0; // initialized ? +static wsrep_uuid_t node_uuid= WSREP_UUID_UNDEFINED; static wsrep_uuid_t cluster_uuid = WSREP_UUID_UNDEFINED; static char cluster_uuid_str[40]= { 0, }; static const char* cluster_status_str[WSREP_VIEW_MAX] = @@ -212,11 +240,25 @@ long long wsrep_local_bf_aborts = 0; const char* wsrep_provider_name = provider_name; const char* wsrep_provider_version = provider_version; const char* wsrep_provider_vendor = provider_vendor; +char* wsrep_provider_capabilities = NULL; +char* wsrep_cluster_capabilities = NULL; /* End wsrep status variables */ -wsrep_uuid_t local_uuid = WSREP_UUID_UNDEFINED; -wsrep_seqno_t local_seqno = WSREP_SEQNO_UNDEFINED; -long wsrep_protocol_version = 3; +wsrep_uuid_t local_uuid = WSREP_UUID_UNDEFINED; +wsrep_seqno_t local_seqno = WSREP_SEQNO_UNDEFINED; +wsp::node_status local_status; +static wsrep_view_status_t local_view_status = WSREP_VIEW_NON_PRIMARY; + +class SR_storage_file *wsrep_SR_store_file = NULL; +class SR_storage_table *wsrep_SR_store_table = NULL; +class SR_storage *wsrep_SR_store = NULL; + +/* + */ +#define WSREP_THD_POOL_SIZE 16 +Wsrep_thd_pool* wsrep_thd_pool= 0; +Wsrep_schema *wsrep_schema= 0; +static bool wsrep_schema_inited= false; wsp::Config_state *wsrep_config_state; @@ -259,8 +301,8 @@ void wsrep_log(void (*fun)(const char *, ...), const char *format, ...) static void wsrep_log_states (wsrep_log_level_t const level, const wsrep_uuid_t* const group_uuid, wsrep_seqno_t const group_seqno, - const wsrep_uuid_t* const node_uuid, - wsrep_seqno_t const node_seqno) + const wsrep_uuid_t* const loc_uuid, + wsrep_seqno_t const loc_seqno) { char uuid_str[37]; char msg[256]; @@ -270,9 +312,9 @@ static void wsrep_log_states (wsrep_log_level_t const level, uuid_str, (long long)group_seqno); wsrep_log_cb (level, msg); - wsrep_uuid_print (node_uuid, uuid_str, sizeof(uuid_str)); + wsrep_uuid_print (loc_uuid, uuid_str, sizeof(uuid_str)); snprintf (msg, 255, "WSREP: Local state: %s:%lld", - uuid_str, (long long)node_seqno); + uuid_str, (long long)loc_seqno); wsrep_log_cb (level, msg); } @@ -281,14 +323,19 @@ void wsrep_init_sidno(const wsrep_uuid_t& wsrep_uuid) { /* generate new Sid map entry from inverted uuid */ rpl_sid sid; - wsrep_uuid_t ltid_uuid; - - for (size_t i= 0; i < sizeof(ltid_uuid.data); ++i) + if (wsrep_protocol_version >= 4) { + sid.copy_from(wsrep_uuid.data); + } + else + { + wsrep_uuid_t ltid_uuid; + for (size_t i= 0; i < sizeof(ltid_uuid.data); ++i) + { ltid_uuid.data[i] = ~wsrep_uuid.data[i]; + } + sid.copy_from(ltid_uuid.data); } - - sid.copy_from(ltid_uuid.data); global_sid_lock->wrlock(); wsrep_sidno= global_sid_map->add_sid(sid); WSREP_INFO("Initialized wsrep sidno %d", wsrep_sidno); @@ -296,19 +343,187 @@ void wsrep_init_sidno(const wsrep_uuid_t& wsrep_uuid) } #endif /* GTID_SUPPORT */ -static wsrep_cb_status_t -wsrep_view_handler_cb (void* app_ctx, - void* recv_ctx, - const wsrep_view_info_t* view, - const char* state, - size_t state_len, - void** sst_req, - size_t* sst_req_len) +void wsrep_init_schema() { - *sst_req = NULL; - *sst_req_len = 0; + WSREP_INFO("wsrep_init_schema_and_SR %p %p", wsrep_schema, wsrep_SR_store); + if (!wsrep_schema) + { + if (wsrep_before_SE()) { + delete wsrep_thd_pool; + wsrep_thd_pool=0; + } + + if (!wsrep_thd_pool) { + wsrep_thd_pool= new Wsrep_thd_pool(WSREP_THD_POOL_SIZE); + } + + wsrep_schema= new Wsrep_schema(wsrep_thd_pool); + + if (strcmp (wsrep_provider, WSREP_NONE)) + { + if (wsrep_schema->init()) + { + WSREP_ERROR("Failed to init wsrep schema"); + delete wsrep_schema; + delete wsrep_thd_pool; + unireg_abort(1); + } + } + } +} + +void wsrep_init_SR() +{ + /* initialize SR pools, now that innodb has initialized */ + if (wsrep_SR_store && wsrep_SR_store->init(wsrep_cluster_state_uuid, + wsrep_schema)) { + WSREP_ERROR("wsrep SR persistency store initialization failed"); + unireg_abort(1); + } + else { + if (wsrep_SR_store && wsrep_SR_store->restore(0)) { + WSREP_ERROR("wsrep SR persistency restore failed"); + unireg_abort(1); + } + } +} + +int wsrep_replay_from_SR_store(THD* thd, const wsrep_trx_meta_t& meta) +{ + DBUG_ENTER("wsrep_replay_from_SR_store"); + if (!wsrep_SR_store) { + WSREP_ERROR("no SR persistency store defined, can't replay"); + DBUG_RETURN(1); + } + + int ret= wsrep_SR_store->replay_trx(thd, meta); + DBUG_RETURN(ret); +} + +static void wsrep_rollback_SR_connections() +{ + THD *tmp; + mysql_mutex_lock(&LOCK_thread_count); + + I_List_iterator<THD> it(threads); + while ((tmp=it++)) + { + mysql_mutex_lock(&tmp->LOCK_wsrep_thd); + if (tmp->wsrep_client_thread && tmp->wsrep_is_streaming()) + { + tmp->set_wsrep_conflict_state(MUST_ABORT); + if (tmp->wsrep_query_state() == QUERY_IDLE) + { + wsrep_fire_rollbacker(tmp); + } + /* + No need to send rollback fragment for this trx: slaves rollback + all SR transactions whose master goes non-Primary. + */ + tmp->wsrep_SR_rollback_replicated_for_trx= tmp->wsrep_trx_id(); + } + mysql_mutex_unlock(&tmp->LOCK_wsrep_thd); + } + + mysql_mutex_unlock(&LOCK_thread_count); +} + +/** Export the WSREP provider's capabilities as a human readable string. + * The result is saved in a dynamically allocated string of the form: + * :cap1:cap2:cap3: + */ +static void wsrep_capabilities_export(wsrep_cap_t const cap, char** str) +{ + static const char* names[] = + { + /* Keep in sync with wsrep/wsrep_api.h WSREP_CAP_* macros. */ + "MULTI_MASTER", + "CERTIFICATION", + "PARALLEL_APPLYING", + "TRX_REPLAY", + "ISOLATION", + "PAUSE", + "CAUSAL_READS", + "CAUSAL_TRX", + "INCREMENTAL_WRITESET", + "SESSION_LOCKS", + "DISTRIBUTED_LOCKS", + "CONSISTENCY_CHECK", + "UNORDERED", + "ANNOTATION", + "PREORDERED", + "STREAMING", + "SNAPSHOT", + "NBO", + }; + + std::string s; + for (size_t i = 0; i < sizeof(names) / sizeof(names[0]); ++i) + { + if (cap & (1ULL << i)) + { + if (s.empty()) + { + s = ":"; + } + s += names[i]; + s += ":"; + } + } + + /* A read from the string pointed to by *str may be started at any time, + * so it must never point to free(3)d memory or non '\0' terminated string. */ + + char* const previous = *str; + + *str = strdup(s.c_str()); - wsrep_member_status_t memb_status= wsrep_config_state->get_status(); + if (previous != NULL) + { + free(previous); + } +} + +wsrep_cb_status_t +wsrep_connected_handler_cb(void* app_ctx, + const wsrep_view_info_t* initial_view) +{ + if (initial_view->my_idx < 0) { + WSREP_ERROR("Invalid index %d in initial view", initial_view->my_idx); + return WSREP_CB_FAILURE; + } + + node_uuid= initial_view->members[initial_view->my_idx].id; + cluster_uuid= initial_view->state_id.uuid; + wsrep_cluster_status= cluster_status_str[initial_view->status]; + + char node_uuid_str[WSREP_UUID_STR_LEN + 1]; + (void)wsrep_uuid_print(&node_uuid, node_uuid_str, sizeof(node_uuid_str)); + (void)wsrep_uuid_print(&cluster_uuid, cluster_uuid_str, + sizeof(cluster_uuid_str)); + + WSREP_INFO("Connected to cluster %s with id: %s", + cluster_uuid_str, node_uuid_str); + return WSREP_CB_SUCCESS; +} + +static wsrep_cb_status_t +wsrep_view_handler_cb(void* app_ctx, + void* recv_ctx, + const wsrep_view_info_t* view, + /* TODO: These are unused, should be removed?*/ + const char* state, + size_t state_len) +{ + /* Allow calling view handler from non-applier threads */ + struct st_my_thread_var* tmp_thread_var= 0; + if (!my_thread_var) { + my_thread_init(); + tmp_thread_var= my_thread_var; + } + + wsrep_cb_status_t ret= WSREP_CB_SUCCESS; + wsrep_member_status_t new_status= local_status.get(); if (memcmp(&cluster_uuid, &view->state_id.uuid, sizeof(wsrep_uuid_t))) { @@ -323,11 +538,16 @@ wsrep_view_handler_cb (void* app_ctx, wsrep_cluster_size= view->memb_num; wsrep_local_index= view->my_idx; - WSREP_INFO("New cluster view: global state: %s:%lld, view# %lld: %s, " - "number of nodes: %ld, my index: %ld, protocol version %d", - wsrep_cluster_state_uuid, (long long)view->state_id.seqno, - (long long)wsrep_cluster_conf_id, wsrep_cluster_status, - wsrep_cluster_size, wsrep_local_index, view->proto_ver); + if (wsrep_cluster_size > 0) { + WSREP_INFO("New cluster view: global state: %s:%lld, view# %lld: %s, " + "number of nodes: %ld, my index: %ld, protocol version %d", + wsrep_cluster_state_uuid, (long long)view->state_id.seqno, + (long long)wsrep_cluster_conf_id, wsrep_cluster_status, + wsrep_cluster_size, wsrep_local_index, view->proto_ver); + } + else { + WSREP_INFO("Provider closed."); + } /* Proceed further only if view is PRIMARY */ if (WSREP_VIEW_PRIMARY != view->status) @@ -338,7 +558,7 @@ wsrep_view_handler_cb (void* app_ctx, #endif /* HAVE_QUERY_CACHE */ wsrep_ready_set(FALSE); - memb_status= WSREP_MEMBER_UNDEFINED; + new_status= WSREP_MEMBER_UNDEFINED; /* Always record local_uuid and local_seqno in non-prim since this * may lead to re-initializing provider and start position is * determined according to these variables */ @@ -355,6 +575,7 @@ wsrep_view_handler_cb (void* app_ctx, case 1: case 2: case 3: + case 4: // SR and view callback change // version change if (view->proto_ver != wsrep_protocol_version) { @@ -374,101 +595,200 @@ wsrep_view_handler_cb (void* app_ctx, unireg_abort(1); } - if (view->state_gap) + if (memcmp(&cluster_uuid, &view->state_id.uuid, sizeof(wsrep_uuid_t))) { - WSREP_WARN("Gap in state sequence. Need state transfer."); - - /* After that wsrep will call wsrep_sst_prepare. */ - /* keep ready flag 0 until we receive the snapshot */ - wsrep_ready_set(FALSE); - - /* Close client connections to ensure that they don't interfere - * with SST. Necessary only if storage engines are initialized - * before SST. - * TODO: Just killing all ongoing transactions should be enough - * since wsrep_ready is OFF and no new transactions can start. - */ - if (!wsrep_before_SE()) - { - WSREP_DEBUG("[debug]: closing client connections for PRIM"); - wsrep_close_client_connections(FALSE); - } + memcpy((wsrep_uuid_t*)&cluster_uuid, &view->state_id.uuid, + sizeof(cluster_uuid)); - ssize_t const req_len= wsrep_sst_prepare (sst_req); - - if (req_len < 0) - { - WSREP_ERROR("SST preparation failed: %zd (%s)", -req_len, - strerror(-req_len)); - memb_status= WSREP_MEMBER_UNDEFINED; - } - else - { - assert(sst_req != NULL); - *sst_req_len= req_len; - memb_status= WSREP_MEMBER_JOINER; - } + wsrep_uuid_print (&cluster_uuid, cluster_uuid_str, + sizeof(cluster_uuid_str)); } - else + + /* + * NOTE: Initialize wsrep_group_uuid here only if it wasn't initialized + * before - OR - it was reinitilized on startup (lp:992840) + */ + if (wsrep_startup) { - /* - * NOTE: Initialize wsrep_group_uuid here only if it wasn't initialized - * before - OR - it was reinitilized on startup (lp:992840) - */ - if (wsrep_startup) - { if (wsrep_before_SE()) { wsrep_SE_init_grab(); // Signal mysqld init thread to continue wsrep_sst_complete (&cluster_uuid, view->state_id.seqno, false); // and wait for SE initialization - wsrep_SE_init_wait(); + if (wsrep_SE_init_wait()) + { + ret= WSREP_CB_FAILURE; + goto out; + } + } + + wsrep_seqno_t seqno; + + /* Init storage engine XIDs from first view */ + if (view->memb_num == 1) + { + seqno= view->state_id.seqno; + wsrep_set_SE_checkpoint(WSREP_UUID_UNDEFINED, WSREP_SEQNO_UNDEFINED); + wsrep_set_SE_checkpoint(cluster_uuid, seqno); } else { - local_uuid= cluster_uuid; - local_seqno= view->state_id.seqno; + // must get from state transfer + wsrep_uuid_t unused; + wsrep_get_SE_checkpoint(unused, seqno); } - /* Init storage engine XIDs from first view */ - wsrep_set_SE_checkpoint(local_uuid, local_seqno); + + wsrep_verify_SE_checkpoint(cluster_uuid, seqno); + new_status= WSREP_MEMBER_JOINED; #ifdef GTID_SUPPORT wsrep_init_sidno(local_uuid); #endif /* GTID_SUPPORT */ - memb_status= WSREP_MEMBER_JOINED; - } + } + else + { + wsrep_get_SE_checkpoint(local_uuid, local_seqno); - // just some sanity check - if (memcmp (&local_uuid, &cluster_uuid, sizeof (wsrep_uuid_t))) - { - WSREP_ERROR("Undetected state gap. Can't continue."); - wsrep_log_states(WSREP_LOG_FATAL, &cluster_uuid, view->state_id.seqno, - &local_uuid, -1); - unireg_abort(1); - } + // just a sanity check + if (wsrep_uuid_compare(&local_uuid, &cluster_uuid) != 0) + { + WSREP_ERROR("Undetected state gap. Can't continue."); + wsrep_log_states(WSREP_LOG_FATAL, &cluster_uuid, view->state_id.seqno, + &local_uuid, local_seqno); + unireg_abort(1); + } } - if (wsrep_auto_increment_control) + if (wsrep_auto_increment_control && view->my_idx >= 0) { - global_system_variables.auto_increment_offset= view->my_idx + 1; - global_system_variables.auto_increment_increment= view->memb_num; + global_system_variables.auto_increment_offset= view->my_idx + 1; + global_system_variables.auto_increment_increment= view->memb_num; } { /* capabilities may be updated on new configuration */ - uint64_t const caps(wsrep->capabilities (wsrep)); + wsrep_cap_t const caps(view->capabilities); - my_bool const idc((caps & WSREP_CAP_INCREMENTAL_WRITESET) != 0); - if (TRUE == wsrep_incremental_data_collection && FALSE == idc) - { - WSREP_WARN("Unsupported protocol downgrade: " - "incremental data collection disabled. Expect abort."); - } - wsrep_incremental_data_collection = idc; + my_bool const idc((caps & WSREP_CAP_INCREMENTAL_WRITESET) != 0); + if (TRUE == wsrep_incremental_data_collection && FALSE == idc) + { + WSREP_WARN("Unsupported protocol downgrade: " + "incremental data collection disabled. Expect abort."); + } + wsrep_incremental_data_collection = idc; + + wsrep_capabilities_export(caps, &wsrep_cluster_capabilities); + } + + /* + Initialize wsrep schema and SR + */ + if (!wsrep_schema) { + wsrep_init_schema(); + } + + if (wsrep_schema->store_view(view)) { + WSREP_ERROR("Storing view failed"); + unireg_abort(1); + } + + /* + If the recv_ctx is a pointer to thd object we need to store globals + here as wsrep_schema->store_view() uses temporary thd object and + writes over thread locals. + */ + if (recv_ctx) ((THD*) recv_ctx)->store_globals(); + + if (wsrep_startup == TRUE) { + wsrep_init_SR(); + } + + trim_SR_pool((THD*)recv_ctx, view->members, view->memb_num); + + /* + Transitioning from non-primary to primary view + */ + if (local_view_status != WSREP_VIEW_PRIMARY) { + wsrep_rollback_SR_connections(); } out: if (view->status == WSREP_VIEW_PRIMARY) wsrep_startup= FALSE; - wsrep_config_state->set(memb_status, view); + local_status.set(new_status, view); + local_view_status = view->status; + + if (tmp_thread_var) { + my_thread_end(); + } + + return ret; +} + +/* Verifies that SE position is consistent with the group position + * and initializes other variables */ +void wsrep_verify_SE_checkpoint(const wsrep_uuid_t& uuid, + wsrep_seqno_t const seqno) +{ + wsrep_get_SE_checkpoint(local_uuid, local_seqno); + + if (memcmp(&local_uuid, &uuid, sizeof (wsrep_uuid_t)) || + local_seqno > seqno) + { + WSREP_ERROR("Failed to update SE checkpoint. Can't continue."); + wsrep_log_states(WSREP_LOG_FATAL, &uuid, seqno, + &local_uuid, local_seqno); + assert(0); + unireg_abort(1); + } + +#ifdef GTID_SUPPORT + wsrep_init_sidno(local_uuid); +#endif +} + +static wsrep_cb_status_t +wsrep_sst_request_cb (void* app_ctx, + void** sst_req, + size_t* sst_req_len) +{ + *sst_req = NULL; + *sst_req_len = 0; + + wsrep_member_status_t new_status= local_status.get(); + + WSREP_INFO("Preparing to receive SST."); + + /* After that wsrep will call wsrep_sst_prepare. */ + /* keep ready flag 0 until we receive the snapshot */ + wsrep_ready_set(FALSE); + + /* Close client connections to ensure that they don't interfere + * with SST. Necessary only if storage engines are initialized + * before SST. + * TODO: Just killing all ongoing transactions should be enough + * since wsrep_ready is OFF and no new transactions can start. + */ + if (!wsrep_before_SE()) + { + WSREP_DEBUG("[debug]: closing client connections for SST"); + wsrep_close_client_connections(TRUE); + } + + ssize_t const req_len = wsrep_sst_prepare (sst_req); + + if (req_len < 0) + { + WSREP_ERROR("SST preparation failed: %zd (%s)", -req_len, + strerror(-req_len)); + new_status= WSREP_MEMBER_UNDEFINED; + } + else + { + assert(*sst_req != NULL || 0 == req_len); + *sst_req_len= req_len; + new_status= WSREP_MEMBER_JOINER; + } + + local_status.set(new_status); return WSREP_CB_SUCCESS; } @@ -516,11 +836,12 @@ void wsrep_ready_wait () mysql_mutex_unlock (&LOCK_wsrep_ready); } -static void wsrep_synced_cb(void* app_ctx) +static wsrep_cb_status_t wsrep_synced_cb(void* app_ctx) { WSREP_INFO("Synchronized with group, ready for connections"); - my_bool signal_main= wsrep_ready_set(TRUE); wsrep_config_state->set(WSREP_MEMBER_SYNCED); + my_bool signal_main= wsrep_ready_set(TRUE); + local_status.set(WSREP_MEMBER_SYNCED); if (signal_main) { @@ -528,7 +849,10 @@ static void wsrep_synced_cb(void* app_ctx) // Signal mysqld init thread to continue wsrep_sst_complete (&local_uuid, local_seqno, false); // and wait for SE initialization - wsrep_SE_init_wait(); + if (wsrep_SE_init_wait()) + { + return WSREP_CB_FAILURE; + } } if (wsrep_restart_slave_activated) { @@ -550,6 +874,7 @@ static void wsrep_synced_cb(void* app_ctx) mysql_mutex_unlock(&LOCK_active_mi); } + return WSREP_CB_SUCCESS; } static void wsrep_init_position() @@ -559,7 +884,7 @@ static void wsrep_init_position() wsrep_seqno_t seqno; wsrep_get_SE_checkpoint(uuid, seqno); - if (!memcmp(&uuid, &WSREP_UUID_UNDEFINED, sizeof(wsrep_uuid_t))) + if (wsrep_uuid_compare(&uuid, &WSREP_UUID_UNDEFINED) == 0) { WSREP_INFO("Read nil XID from storage engines, skipping position init"); return; @@ -567,9 +892,10 @@ static void wsrep_init_position() char uuid_str[40] = {0, }; wsrep_uuid_print(&uuid, uuid_str, sizeof(uuid_str)); - WSREP_INFO("Initial position: %s:%lld", uuid_str, (long long)seqno); + WSREP_INFO("Storage engines initial position: %s:%lld", + uuid_str, (long long)seqno); - if (!memcmp(&local_uuid, &WSREP_UUID_UNDEFINED, sizeof(local_uuid)) && + if (wsrep_uuid_compare(&local_uuid, &WSREP_UUID_UNDEFINED) == 0 && local_seqno == WSREP_SEQNO_UNDEFINED) { // Initial state @@ -594,6 +920,7 @@ int wsrep_init() if (strcmp(wsrep_start_position, WSREP_START_POSITION_ZERO) && wsrep_start_position_init(wsrep_start_position)) { + assert(0); return 1; } @@ -653,6 +980,17 @@ int wsrep_init() wsrep->provider_vendor, sizeof(provider_vendor) - 1); } + if (wsrep_gtid_mode && opt_bin_log && !opt_log_slave_updates) + { + WSREP_ERROR("Option --log-slave-updates is required if " + "binlog is enabled, GTID mode is on and wsrep provider " + "is specified"); + return -1; + } + + if (!wsrep_data_home_dir || strlen(wsrep_data_home_dir) == 0) + wsrep_data_home_dir = mysql_real_data_home; + /* Initialize node address */ char node_addr[512]= { 0, }; size_t const node_addr_max= sizeof(node_addr) - 1; @@ -747,9 +1085,11 @@ int wsrep_init() done: struct wsrep_init_args wsrep_args; + memset(&wsrep_args, 0, sizeof(wsrep_args)); struct wsrep_gtid const state_id = { local_uuid, local_seqno }; + wsrep_args.app_ctx = 0; wsrep_args.data_dir = wsrep_data_home_dir; wsrep_args.node_name = (wsrep_node_name) ? wsrep_node_name : ""; wsrep_args.node_address = node_addr; @@ -761,9 +1101,10 @@ done: wsrep_args.state_id = &state_id; wsrep_args.logger_cb = wsrep_log_cb; - wsrep_args.view_handler_cb = wsrep_view_handler_cb; + wsrep_args.connected_cb = wsrep_connected_handler_cb; + wsrep_args.view_cb = wsrep_view_handler_cb; + wsrep_args.sst_request_cb = wsrep_sst_request_cb; wsrep_args.apply_cb = wsrep_apply_cb; - wsrep_args.commit_cb = wsrep_commit_cb; wsrep_args.unordered_cb = wsrep_unordered_cb; wsrep_args.sst_donate_cb = wsrep_sst_donate_cb; wsrep_args.synced_cb = wsrep_synced_cb; @@ -777,8 +1118,44 @@ done: wsrep->free(wsrep); free(wsrep); wsrep = NULL; - } else { - wsrep_inited= 1; + return rcode; + } + + if (!wsrep_provider_is_SR_capable() && + global_system_variables.wsrep_trx_fragment_size > 0) + { + WSREP_ERROR("The WSREP provider (%s) does not support streaming " + "replication but wsrep_trx_fragment_size is set to a " + "value other than 0 (%lu). Cannot continue. Either set " + "wsrep_trx_fragment_size to 0 or use wsrep_provider that " + "supports streaming replication.", + wsrep_provider, global_system_variables.wsrep_trx_fragment_size); + wsrep->free(wsrep); + free(wsrep); + wsrep = NULL; + return -1; + } + wsrep_inited= 1; + + wsrep_capabilities_export(wsrep->capabilities(wsrep), + &wsrep_provider_capabilities); + + WSREP_DEBUG("SR storage init for: %s", + (wsrep_SR_store_type == WSREP_SR_STORE_TABLE) ? "table" : + (wsrep_SR_store_type == WSREP_SR_STORE_FILE) ? "file" : "void"); + + switch (wsrep_SR_store_type) + { + case WSREP_SR_STORE_FILE: + wsrep_SR_store = wsrep_SR_store_file = + new SR_storage_file(mysql_real_data_home_ptr, + 1024, + wsrep_cluster_state_uuid); + break; + case WSREP_SR_STORE_TABLE: + wsrep_SR_store = wsrep_SR_store_table = new SR_storage_table(); + break; + case WSREP_SR_STORE_NONE: break; } return rcode; @@ -802,25 +1179,35 @@ void wsrep_thr_init() mysql_cond_init(key_COND_wsrep_sst, &COND_wsrep_sst, NULL); mysql_mutex_init(key_LOCK_wsrep_sst_init, &LOCK_wsrep_sst_init, MY_MUTEX_INIT_FAST); mysql_cond_init(key_COND_wsrep_sst_init, &COND_wsrep_sst_init, NULL); - mysql_mutex_init(key_LOCK_wsrep_rollback, &LOCK_wsrep_rollback, MY_MUTEX_INIT_FAST); - mysql_cond_init(key_COND_wsrep_rollback, &COND_wsrep_rollback, NULL); mysql_mutex_init(key_LOCK_wsrep_replaying, &LOCK_wsrep_replaying, MY_MUTEX_INIT_FAST); mysql_cond_init(key_COND_wsrep_replaying, &COND_wsrep_replaying, NULL); mysql_mutex_init(key_LOCK_wsrep_slave_threads, &LOCK_wsrep_slave_threads, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_wsrep_desync, &LOCK_wsrep_desync, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_wsrep_config_state, &LOCK_wsrep_config_state, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_wsrep_SR_pool, + &LOCK_wsrep_SR_pool, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_wsrep_SR_store, + &LOCK_wsrep_SR_store, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_wsrep_thd_pool, + &LOCK_wsrep_thd_pool, MY_MUTEX_INIT_FAST); DBUG_VOID_RETURN; } +extern int wsrep_on(void *); + void wsrep_init_startup (bool first) { if (wsrep_init()) unireg_abort(1); +#ifdef OLD_MARIADB wsrep_thr_lock_init( (wsrep_thd_is_brute_force_fun)wsrep_thd_is_BF, (wsrep_abort_thd_fun)wsrep_abort_thd, wsrep_debug, wsrep_convert_LOCK_to_trx, (wsrep_on_fun)wsrep_on); +#endif + wsrep_thr_lock_init(wsrep_thd_is_BF, wsrep_abort_thd, + wsrep_debug, wsrep_convert_LOCK_to_trx, wsrep_on); /* Pre-initialize global_system_variables.table_plugin with a dummy engine @@ -853,6 +1240,14 @@ void wsrep_init_startup (bool first) void wsrep_deinit(bool free_options) { DBUG_ASSERT(wsrep_inited == 1); + if (wsrep_schema) + delete wsrep_schema; + wsrep_schema= 0; + WSREP_DEBUG("wsrep_deinit, free %d", free_options); + if (wsrep_thd_pool) + delete wsrep_thd_pool; + wsrep_thd_pool= 0; + wsrep_unload(wsrep); wsrep= 0; provider_name[0]= '\0'; @@ -861,9 +1256,16 @@ void wsrep_deinit(bool free_options) wsrep_inited= 0; - if (free_options) + if (wsrep_provider_capabilities != NULL) { - wsrep_sst_auth_free(); + char* p = wsrep_provider_capabilities; + wsrep_provider_capabilities = NULL; + free(p); + + if (free_options) + { + wsrep_sst_auth_free(); + } } } @@ -872,28 +1274,42 @@ void wsrep_thr_deinit() { if (!wsrep_config_state) return; // Never initialized + WSREP_DEBUG("wsrep_thr_deinit"); mysql_mutex_destroy(&LOCK_wsrep_ready); mysql_cond_destroy(&COND_wsrep_ready); mysql_mutex_destroy(&LOCK_wsrep_sst); mysql_cond_destroy(&COND_wsrep_sst); mysql_mutex_destroy(&LOCK_wsrep_sst_init); mysql_cond_destroy(&COND_wsrep_sst_init); - mysql_mutex_destroy(&LOCK_wsrep_rollback); - mysql_cond_destroy(&COND_wsrep_rollback); mysql_mutex_destroy(&LOCK_wsrep_replaying); mysql_cond_destroy(&COND_wsrep_replaying); mysql_mutex_destroy(&LOCK_wsrep_slave_threads); mysql_mutex_destroy(&LOCK_wsrep_desync); mysql_mutex_destroy(&LOCK_wsrep_config_state); + mysql_mutex_destroy(&LOCK_wsrep_SR_pool); + mysql_mutex_destroy(&LOCK_wsrep_SR_store); + mysql_mutex_destroy(&LOCK_wsrep_thd_pool); + delete wsrep_config_state; wsrep_config_state= 0; // Safety + + if (wsrep_cluster_capabilities != NULL) + { + char* p = wsrep_cluster_capabilities; + wsrep_cluster_capabilities = NULL; + free(p); + } } void wsrep_recover() { - char uuid_str[40]; + wsrep_uuid_t uuid; + wsrep_seqno_t seqno; + wsrep_get_SE_checkpoint(uuid, seqno); + char uuid_str[40] = {0, };; + wsrep_uuid_print(&uuid, uuid_str, sizeof(uuid_str)); - if (!memcmp(&local_uuid, &WSREP_UUID_UNDEFINED, sizeof(wsrep_uuid_t)) && + if (wsrep_uuid_compare(&local_uuid, &WSREP_UUID_UNDEFINED) == 0 && local_seqno == -2) { wsrep_uuid_print(&local_uuid, uuid_str, sizeof(uuid_str)); @@ -901,10 +1317,6 @@ void wsrep_recover() uuid_str, (long long)local_seqno); return; } - wsrep_uuid_t uuid; - wsrep_seqno_t seqno; - wsrep_get_SE_checkpoint(uuid, seqno); - wsrep_uuid_print(&uuid, uuid_str, sizeof(uuid_str)); WSREP_INFO("Recovered position: %s:%lld", uuid_str, (long long)seqno); } @@ -924,17 +1336,56 @@ void wsrep_stop_replication(THD *thd) wsrep_connected= FALSE; - wsrep_close_client_connections(TRUE); - + /* my connection, should not terminate with wsrep_close_client_connection(), + make transaction to rollback + */ + if (thd && !thd->wsrep_applier) trans_rollback(thd); + wsrep_close_client_connections(TRUE, thd); + /* wait until appliers have stopped */ wsrep_wait_appliers_close(thd); + node_uuid= WSREP_UUID_UNDEFINED; + + delete wsrep_schema; + wsrep_schema= 0; + return; } +void wsrep_shutdown_replication() +{ + WSREP_INFO("Shutdown replication"); + if (!wsrep) + { + WSREP_INFO("Provider was not loaded, in shutdown replication"); + return; + } + + /* disconnect from group first to get wsrep_ready == FALSE */ + WSREP_DEBUG("Provider disconnect"); + wsrep->disconnect(wsrep); + wsrep_connected= FALSE; + + wsrep_close_client_connections(TRUE); + wsrep_close_SR_transactions(NULL); + + /* wait until appliers have stopped */ + wsrep_wait_appliers_close(NULL); + node_uuid= WSREP_UUID_UNDEFINED; + + if (current_thd) + { + /* Undocking the thread specific data. */ + my_pthread_setspecific_ptr(THR_THD, NULL); + //my_pthread_setspecific_ptr(THR_MALLOC, NULL); + } +} + bool wsrep_start_replication() { wsrep_status_t rcode; + WSREP_DEBUG("wsrep_start_replication"); /* wsrep provider must be loaded. */ DBUG_ASSERT(wsrep); @@ -957,7 +1408,27 @@ bool wsrep_start_replication() return true; } - bool const bootstrap= wsrep_new_cluster; + /* + With mysqldump etc SST THD pool must be initialized before starting + replication in order to avoid deadlock between THD pool initialization + and possible causal read of status variables. + + On the other hand, with SST methods that require starting wsrep first + plugins are not necessarily initialized at this point, so THD pool + initialization must be postponed until plugin init has been done and + before wsrep schema is initialized. + */ + if (!wsrep_before_SE()) + { + WSREP_DEBUG("thd pool init for mysqldump SST"); + if (wsrep_thd_pool) delete wsrep_thd_pool; + wsrep_thd_pool= new Wsrep_thd_pool(WSREP_THD_POOL_SIZE); + } + wsrep_init_SR_pool(); + wsrep_startup= TRUE; + + bool const bootstrap(TRUE == wsrep_new_cluster); + wsrep_new_cluster= FALSE; WSREP_INFO("Start replication"); @@ -1000,13 +1471,17 @@ bool wsrep_start_replication() bool wsrep_must_sync_wait (THD* thd, uint mask) { - return (thd->variables.wsrep_sync_wait & mask) && + bool ret; + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + ret= (thd->variables.wsrep_sync_wait & mask) && thd->variables.wsrep_on && !(thd->variables.wsrep_dirty_reads && !is_update_query(thd->lex->sql_command)) && !thd->in_active_multi_stmt_transaction() && - thd->wsrep_conflict_state != REPLAYING && + thd->wsrep_conflict_state() != REPLAYING && thd->wsrep_sync_wait_gtid.seqno == WSREP_SEQNO_UNDEFINED; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + return ret; } bool wsrep_sync_wait (THD* thd, uint mask) @@ -1017,7 +1492,7 @@ bool wsrep_sync_wait (THD* thd, uint mask) thd->variables.wsrep_sync_wait, mask); // This allows autocommit SELECTs and a first SELECT after SET AUTOCOMMIT=0 // TODO: modify to check if thd has locked any rows. - wsrep_status_t ret= wsrep->causal_read (wsrep, &thd->wsrep_sync_wait_gtid); + wsrep_status_t ret = wsrep_sync_wait_upto(thd, NULL, -1); if (unlikely(WSREP_OK != ret)) { @@ -1051,6 +1526,16 @@ bool wsrep_sync_wait (THD* thd, uint mask) return false; } +wsrep_status_t wsrep_sync_wait_upto (THD* thd, + wsrep_gtid_t* upto, + int timeout) +{ + return wsrep->sync_wait(wsrep, + upto, + timeout, + &thd->wsrep_sync_wait_gtid); +} + void wsrep_keys_free(wsrep_key_arr_t* key_arr) { for (size_t i= 0; i < key_arr->keys_len; ++i) @@ -1074,9 +1559,9 @@ void wsrep_keys_free(wsrep_key_arr_t* key_arr) */ static bool wsrep_prepare_key_for_isolation(const char* db, - const char* table, - wsrep_buf_t* key, - size_t* key_len) + const char* table, + wsrep_buf_t* key, + size_t* key_len) { if (*key_len < 2) return false; @@ -1088,6 +1573,7 @@ static bool wsrep_prepare_key_for_isolation(const char* db, case 1: case 2: case 3: + case 4: { *key_len= 0; if (db) @@ -1109,13 +1595,20 @@ static bool wsrep_prepare_key_for_isolation(const char* db, break; } default: + assert(0); + WSREP_ERROR("Unsupported protocol version: %ld", wsrep_protocol_version); + unireg_abort(1); return false; } return true; } -/* Prepare key list from db/table and table_list */ +/* + * Prepare key list from db/table and table_list + * + * Return zero in case of success, 1 in case of failure. + */ bool wsrep_prepare_keys_for_isolation(THD* thd, const char* db, const char* table, @@ -1138,7 +1631,7 @@ bool wsrep_prepare_keys_for_isolation(THD* thd, { WSREP_ERROR("Can't allocate memory for key_parts"); goto err; - } + } ka->keys[0].key_parts_num= 2; if (!wsrep_prepare_key_for_isolation( db, table, @@ -1153,13 +1646,9 @@ bool wsrep_prepare_keys_for_isolation(THD* thd, for (const TABLE_LIST* table= table_list; table; table= table->next_global) { wsrep_key_t* tmp; - if (ka->keys) - tmp= (wsrep_key_t*)my_realloc(ka->keys, + tmp= (wsrep_key_t*)my_realloc(ka->keys, (ka->keys_len + 1) * sizeof(wsrep_key_t), - MYF(0)); - else - tmp= (wsrep_key_t*)my_malloc((ka->keys_len + 1) * sizeof(wsrep_key_t), MYF(0)); - + MY_ALLOW_ZERO_PTR); if (!tmp) { WSREP_ERROR("Can't allocate memory for key_array"); @@ -1182,13 +1671,13 @@ bool wsrep_prepare_keys_for_isolation(THD* thd, goto err; } } - return 0; + return false; err: wsrep_keys_free(ka); - return 1; + return true; } - +#ifdef OUT bool wsrep_prepare_key(const uchar* cache_key, size_t cache_key_len, const uchar* row_id, size_t row_id_len, wsrep_buf_t* key, size_t* key_len) @@ -1209,6 +1698,7 @@ bool wsrep_prepare_key(const uchar* cache_key, size_t cache_key_len, case 1: case 2: case 3: + case 4: { key[0].ptr = cache_key; key[0].len = strlen( (char*)cache_key ); @@ -1229,7 +1719,101 @@ bool wsrep_prepare_key(const uchar* cache_key, size_t cache_key_len, return true; } +#endif +bool wsrep_prepare_key_for_innodb(THD* thd, + const uchar* cache_key, + size_t cache_key_len, + const uchar* row_id, + size_t row_id_len, + wsrep_buf_t* key, + size_t* key_len) +{ + + if (*key_len < 3) return false; + + *key_len= 0; + switch (wsrep_protocol_version) + { + case 0: + { + key[0].ptr = cache_key; + key[0].len = cache_key_len; + + *key_len = 1; + break; + } + case 1: + case 2: + case 3: + case 4: + { + key[0].ptr = cache_key; + key[0].len = strlen( (char*)cache_key ); + + key[1].ptr = cache_key + strlen( (char*)cache_key ) + 1; + key[1].len = strlen( (char*)(key[1].ptr) ); + + *key_len = 2; + break; + } + default: + assert(0); + WSREP_ERROR("Unsupported protocol version: %ld", wsrep_protocol_version); + unireg_abort(1); + return false; + } + + key[*key_len].ptr = row_id; + key[*key_len].len = row_id_len; + ++(*key_len); + + return true; +} + +bool wsrep_append_SR_keys(THD* thd) +{ + wsrep_key_set::iterator db_it; + for (db_it = thd->wsrep_SR_keys.begin(); + db_it != thd->wsrep_SR_keys.end(); + ++db_it) + { + const std::string& db(db_it->first); + wsrep_key_set::mapped_type& table_names(db_it->second); + wsrep_key_set::mapped_type::iterator table_it; + for (table_it = table_names.begin(); + table_it != table_names.end(); + ++table_it) + { + size_t parts_len(2); + wsrep_buf_t parts[2]; + if (!wsrep_prepare_key_for_isolation(db.c_str(), + (*table_it).c_str(), + parts, + &parts_len)) + { + WSREP_ERROR("Failed to prepare key for streaming transaction, %s", + thd->query()); + return false; + } + + wsrep_key_t key = {parts, parts_len}; + if (wsrep->append_key(wsrep, + &thd->wsrep_ws_handle, + &key, + 1, + WSREP_KEY_SHARED, + true)) + { + WSREP_ERROR("Failed to append key for streaming transaction, %s", + thd->query()); + return false; + } + } + } + + return true; +} /* * Construct Query_log_Event from thd query and serialize it @@ -1241,7 +1825,7 @@ int wsrep_to_buf_helper( THD* thd, const char *query, uint query_len, uchar** buf, size_t* buf_len) { IO_CACHE tmp_io_cache; - Log_event_writer writer(&tmp_io_cache,0); + Log_event_writer writer(&tmp_io_cache, 0); if (open_cached_file(&tmp_io_cache, mysql_tmpdir, TEMP_PREFIX, 65536, MYF(MY_WME))) return 1; @@ -1399,8 +1983,97 @@ create_view_query(THD *thd, uchar** buf, size_t* buf_len) } /* Forward declarations. */ -static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len); -static int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len); +int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len); +int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len); +/* + Rewrite DROP TABLE for TOI. Temporary tables are eliminated from + the query as they are visible only to client connection. + + TODO: See comments for sql_base.cc:drop_temporary_table() and refine + the function to deal with transactional locked tables. + */ +static int wsrep_drop_table_query(THD* thd, uchar** buf, size_t* buf_len) +{ + + LEX* lex= thd->lex; + SELECT_LEX* select_lex= lex->first_select_lex(); + TABLE_LIST* first_table= select_lex->table_list.first; + String buff; + + bool found_temp_table= false; + for (TABLE_LIST* table= first_table; table; table= table->next_global) + { + if (thd->find_temporary_table(table->db.str, table->table_name.str)) + { + found_temp_table= true; + break; + } + } + + if (found_temp_table) + { + buff.append("DROP TABLE "); + if (lex->create_info.if_exists()) + buff.append("IF EXISTS "); + + for (TABLE_LIST* table= first_table; table; table= table->next_global) + { + if (!thd->find_temporary_table(table->db.str, table->table_name.str)) + { + append_identifier(thd, &buff, table->db.str, table->db.length); + buff.append("."); + append_identifier(thd, &buff, table->table_name.str, table->table_name.length); + buff.append(","); + } + } + + /* Chop the last comma */ + buff.chop(); + buff.append(" /* generated by wsrep */"); + + WSREP_DEBUG("Rewrote '%s' as '%s'", thd->query(), buff.ptr()); + + return wsrep_to_buf_helper(thd, buff.ptr(), buff.length(), buf, buf_len); + } + else + { + return wsrep_to_buf_helper(thd, thd->query(), thd->query_length(), + buf, buf_len); + } +} + +static int wsrep_TOI_event_buf(THD* thd, uchar** buf, size_t* buf_len) +{ + int err; + switch (thd->lex->sql_command) + { + case SQLCOM_CREATE_VIEW: + err= create_view_query(thd, buf, buf_len); + break; + case SQLCOM_CREATE_PROCEDURE: + case SQLCOM_CREATE_SPFUNCTION: + err= wsrep_create_sp(thd, buf, buf_len); + break; + case SQLCOM_CREATE_TRIGGER: + err= wsrep_create_trigger_query(thd, buf, buf_len); + break; + case SQLCOM_CREATE_EVENT: + err= wsrep_create_event_query(thd, buf, buf_len); + break; + case SQLCOM_ALTER_EVENT: + err= wsrep_alter_event_query(thd, buf, buf_len); + break; + case SQLCOM_DROP_TABLE: + err= wsrep_drop_table_query(thd, buf, buf_len); + break; + default: + err= wsrep_to_buf_helper(thd, thd->query(), thd->query_length(), buf, + buf_len); + break; + } + + return err; +} /* Decide if statement should run in TOI. @@ -1480,20 +2153,80 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table, } } +static bool wsrep_can_run_in_nbo(THD *thd) +{ + switch (thd->lex->sql_command) + { + case SQLCOM_ALTER_TABLE: + /* + CREATE INDEX and DROP INDEX are mapped to ALTER TABLE internally + */ + case SQLCOM_CREATE_INDEX: + case SQLCOM_DROP_INDEX: + switch (thd->lex->alter_info.requested_lock) + { + case Alter_info::ALTER_TABLE_LOCK_SHARED: + case Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE: + return true; + default: + return false; + } + case SQLCOM_OPTIMIZE: + return true; + default: + break; /* Keep compiler happy */ + } + return false; +} + +static void wsrep_TOI_begin_failed(THD* thd, const wsrep_buf_t* const err) +{ + if (wsrep_thd_trx_seqno(thd) > 0) + { + /* GTID was granted and TO acquired - need to log event and release TO */ + if (wsrep_emulate_bin_log) wsrep_thd_binlog_trx_reset(thd); + if (wsrep_write_dummy_event(thd, "TOI begin failed")) { goto fail; } + wsrep_xid_init(&thd->wsrep_xid, + thd->wsrep_trx_meta.gtid.uuid, + thd->wsrep_trx_meta.gtid.seqno); + //if (tc_log) tc_log->commit(thd, true); + if (tc_log) + { + tc_log->log_and_order(thd, thd->transaction.xid_state.xid.get_my_xid(), + true, false, false); + } + wsrep_status_t const rcode= + wsrep->to_execute_end(wsrep, thd->thread_id, err); + if (WSREP_OK != rcode) + { + WSREP_ERROR("Leaving critical section for failed TOI failed: thd: %llu, " + "schema: %s, SQL: %s, rcode: %d", + (long long)thd->real_id, (thd->db.str ? thd->db.str : "(null)"), + thd->query(), rcode); + goto fail; + } + } + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + wsrep_cleanup_transaction(thd); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + return; +fail: + WSREP_ERROR("Failed to release TOI resources. Need to abort."); + unireg_abort(1); +} + /* - returns: + returns: 0: statement was replicated as TOI 1: TOI replication was skipped - -1: TOI replication failed + -1: TOI replication failed + -2: NBO begin failed */ static int wsrep_TOI_begin(THD *thd, const char *db_, const char *table_, const TABLE_LIST* table_list) { - wsrep_status_t ret(WSREP_WARNING); - uchar* buf(0); - size_t buf_len(0); - int buf_err; - int rc= 0; + DBUG_ASSERT(thd->variables.wsrep_OSU_method == WSREP_OSU_TOI || + thd->variables.wsrep_OSU_method == WSREP_OSU_NBO); if (wsrep_can_run_in_toi(thd, db_, table_, table_list) == false) { @@ -1501,74 +2234,178 @@ static int wsrep_TOI_begin(THD *thd, const char *db_, const char *table_, return 1; } - WSREP_DEBUG("TO BEGIN: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd), - thd->wsrep_exec_mode, thd->query() ); - switch (thd->lex->sql_command) + if (thd->variables.wsrep_OSU_method == WSREP_OSU_NBO && + (wsrep->capabilities(wsrep) & WSREP_CAP_NBO) == 0) { - case SQLCOM_CREATE_VIEW: - buf_err= create_view_query(thd, &buf, &buf_len); - break; - case SQLCOM_CREATE_PROCEDURE: - case SQLCOM_CREATE_SPFUNCTION: - buf_err= wsrep_create_sp(thd, &buf, &buf_len); - break; - case SQLCOM_CREATE_TRIGGER: - buf_err= wsrep_create_trigger_query(thd, &buf, &buf_len); - break; - case SQLCOM_CREATE_EVENT: - buf_err= wsrep_create_event_query(thd, &buf, &buf_len); - break; - case SQLCOM_ALTER_EVENT: - buf_err= wsrep_alter_event_query(thd, &buf, &buf_len); - break; - case SQLCOM_CREATE_ROLE: - if (sp_process_definer(thd)) - { - WSREP_WARN("Failed to set CREATE ROLE definer for TOI."); - } - /* fallthrough */ - default: - buf_err= wsrep_to_buf_helper(thd, thd->query(), thd->query_length(), - &buf, &buf_len); - break; + const char* const msg= + "wsrep_OSU_method NBO is not supported by wsrep provider"; + WSREP_DEBUG("%s", msg); + my_message(ER_NOT_SUPPORTED_YET, msg, MYF(0)); + return -1; + } + + bool can_run_in_nbo(wsrep_can_run_in_nbo(thd)); + if (can_run_in_nbo == false && + thd->variables.wsrep_OSU_method == WSREP_OSU_NBO) + { + WSREP_DEBUG("wsrep_OSU_method NBO not supported for %s", + WSREP_QUERY(thd)); + my_message(ER_NOT_SUPPORTED_YET, + "wsrep_OSU_method NBO not supported for query", + MYF(0)); + return -1; } + bool run_in_nbo= (thd->variables.wsrep_OSU_method == WSREP_OSU_NBO && + can_run_in_nbo); + + uint32_t flags= (run_in_nbo ? WSREP_FLAG_TRX_START : + WSREP_FLAG_TRX_START | WSREP_FLAG_TRX_END); + wsrep_status_t ret; + uchar* buf= 0; + size_t buf_len(0); + int buf_err; + int rc; + time_t wait_start; + + buf_err= wsrep_TOI_event_buf(thd, &buf, &buf_len); + if (buf_err) { + WSREP_ERROR("Failed to create TOI event buf: %d", buf_err); + my_message(ER_UNKNOWN_ERROR, + "WSREP replication failed to prepare TOI event buffer. " + "Check your query.", + MYF(0)); + return -1; + } + struct wsrep_buf buff= { buf, buf_len }; + wsrep_key_arr_t key_arr= {0, 0}; - struct wsrep_buf buff = { buf, buf_len }; - if (!buf_err && - !wsrep_prepare_keys_for_isolation(thd, db_, table_, table_list, &key_arr) && - key_arr.keys_len > 0 && - WSREP_OK == (ret = wsrep->to_execute_start(wsrep, thd->thread_id, - key_arr.keys, key_arr.keys_len, - &buff, 1, - &thd->wsrep_trx_meta))) - { - thd->wsrep_exec_mode= TOTAL_ORDER; - wsrep_to_isolation++; - wsrep_keys_free(&key_arr); - WSREP_DEBUG("TO BEGIN: %lld, %d",(long long)wsrep_thd_trx_seqno(thd), - thd->wsrep_exec_mode); - } - else if (key_arr.keys_len > 0) { - /* jump to error handler in mysql_execute_command() */ - WSREP_WARN("TO isolation failed for: %d, schema: %s, sql: %s. Check wsrep " - "connection state and retry the query.", - ret, - thd->get_db(), - (thd->query()) ? thd->query() : "void"); - my_message(ER_LOCK_DEADLOCK, "WSREP replication failed. Check " - "your wsrep connection state and retry the query.", MYF(0)); - wsrep_keys_free(&key_arr); + if (wsrep_prepare_keys_for_isolation(thd, db_, table_, table_list, &key_arr)) { + WSREP_ERROR("Failed to prepare keys for isolation"); + my_message(ER_UNKNOWN_ERROR, + "WSREP replication failed to prepare keys. Check your query.", + MYF(0)); rc= -1; + goto out; } - else { + + /* wsrep_can_run_in_toi() should take care of checking that + DDLs with only temp tables should not be TOId at all */ + DBUG_ASSERT(key_arr.keys_len > 0); + if (key_arr.keys_len == 0) + { /* non replicated DDL, affecting temporary tables only */ - WSREP_DEBUG("TO isolation skipped for: %d, sql: %s." - "Only temporary tables affected.", - ret, (thd->query()) ? thd->query() : "void"); + WSREP_DEBUG("TO isolation skipped, sql: %s." + "Only temporary tables affected.", WSREP_QUERY(thd)); rc= 1; + goto out; + } + + thd_proc_info(thd, "acquiring total order isolation"); + wait_start= time(NULL); + do + { + ret= wsrep->to_execute_start(wsrep, + thd->thread_id, + key_arr.keys, + key_arr.keys_len, + &buff, + 1, + flags, + &thd->wsrep_trx_meta); + + if (thd->killed != NOT_KILLED) break; + + if (ret == WSREP_TRX_FAIL) + { + WSREP_DEBUG("to_execute_start() failed for %lld: %s, NBO: %s, seqno: %lld", + thd->thread_id, WSREP_QUERY(thd), run_in_nbo ? "yes" : "no", + (long long)wsrep_thd_trx_seqno(thd)); + if (ulong(time(NULL) - wait_start) < thd->variables.lock_wait_timeout) + { + usleep(100000); + } + else + { + my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0)); + break; + } + if (run_in_nbo) /* will loop */ + { + wsrep_TOI_begin_failed(thd, NULL /* failed repl/certification doesn't mean error in execution */); + } + } + } while (ret == WSREP_TRX_FAIL && run_in_nbo); + + if (ret != WSREP_OK) { + /* jump to error handler in mysql_execute_command() */ + switch (ret) + { + case WSREP_SIZE_EXCEEDED: + WSREP_WARN("TO isolation failed for: %d, schema: %s, sql: %s. " + "Maximum size exceeded.", + ret, + (thd->db.str ? thd->db.str : "(null)"), + WSREP_QUERY(thd)); + my_error(ER_ERROR_DURING_COMMIT, MYF(0), WSREP_SIZE_EXCEEDED); + break; + default: + WSREP_WARN("TO isolation failed for: %d, schema: %s, sql: %s. " + "Check wsrep connection state and retry the query.", + ret, + (thd->db.str ? thd->db.str : "(null)"), + WSREP_QUERY(thd)); + if (!thd->is_error()) + { + my_error(ER_LOCK_DEADLOCK, MYF(0), "WSREP replication failed. Check " + "your wsrep connection state and retry the query."); + } + } + rc= -1; } + else { + + try { + /* + Allocate dummy thd->wsrep_nbo_ctx to track execution state + in mysql_execute_command(). + */ + if (run_in_nbo) { + thd->wsrep_nbo_ctx= new Wsrep_nbo_ctx(0, 0, 0, wsrep_trx_meta_t()); + } + thd->wsrep_exec_mode= TOTAL_ORDER; + ++wsrep_to_isolation; + WSREP_DEBUG("TO BEGIN(%lld): %lld, %d, %s", + thd->thread_id, + (long long)wsrep_thd_trx_seqno(thd), + thd->wsrep_exec_mode, WSREP_QUERY(thd)); + rc= 0; + + } + catch (std::bad_alloc& e) { + rc= -2; + } + } + + out: if (buf) my_free(buf); + if (key_arr.keys_len) wsrep_keys_free(&key_arr); + + switch(rc) + { + case 0: + break; + case -2: + { + const char* const err_str= "Failed to allocate NBO context object."; + wsrep_buf_t const err= { err_str, strlen(err_str) }; + wsrep_TOI_begin_failed(thd, &err); + break; + } + default: + wsrep_TOI_begin_failed(thd, NULL); + } + return rc; } @@ -1577,21 +2414,43 @@ static void wsrep_TOI_end(THD *thd) { wsrep_to_isolation--; WSREP_DEBUG("TO END: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd), - thd->wsrep_exec_mode, (thd->query()) ? thd->query() : "void"); + thd->wsrep_exec_mode, WSREP_QUERY(thd)); - wsrep_set_SE_checkpoint(thd->wsrep_trx_meta.gtid.uuid, - thd->wsrep_trx_meta.gtid.seqno); - WSREP_DEBUG("TO END: %lld, update seqno", - (long long)wsrep_thd_trx_seqno(thd)); - - if (WSREP_OK == (ret = wsrep->to_execute_end(wsrep, thd->thread_id))) { - WSREP_DEBUG("TO END: %lld", (long long)wsrep_thd_trx_seqno(thd)); + if (wsrep_thd_trx_seqno(thd) != WSREP_SEQNO_UNDEFINED) + { + wsrep_set_SE_checkpoint(thd->wsrep_trx_meta.gtid.uuid, + thd->wsrep_trx_meta.gtid.seqno); + WSREP_DEBUG("TO END: %lld, update seqno", + (long long)wsrep_thd_trx_seqno(thd)); + + if (thd->is_error() && !wsrep_must_ignore_error(thd)) + { + wsrep_apply_error err; + err.store(thd); + + wsrep_buf_t const tmp= err.get_buf(); + ret= wsrep->to_execute_end(wsrep, thd->thread_id, &tmp); + } + else + { + ret= wsrep->to_execute_end(wsrep, thd->thread_id, NULL); + } + + if (WSREP_OK == ret) + { + WSREP_DEBUG("TO END: %lld", (long long)wsrep_thd_trx_seqno(thd)); + } + else + { + WSREP_WARN("TO isolation end failed for: %d, schema: %s, sql: %s", + ret, (thd->db.str ? thd->db.str : "(null)"), WSREP_QUERY(thd)); + } } - else { - WSREP_WARN("TO isolation end failed for: %d, schema: %s, sql: %s", - ret, - thd->get_db(), - (thd->query()) ? thd->query() : "void"); + + if (thd->wsrep_nbo_ctx) + { + delete thd->wsrep_nbo_ctx; + thd->wsrep_nbo_ctx= NULL; } } @@ -1599,7 +2458,7 @@ static int wsrep_RSU_begin(THD *thd, const char *db_, const char *table_) { wsrep_status_t ret(WSREP_WARNING); WSREP_DEBUG("RSU BEGIN: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd), - thd->wsrep_exec_mode, thd->query() ); + thd->wsrep_exec_mode, WSREP_QUERY(thd)); ret = wsrep->desync(wsrep); if (ret != WSREP_OK) @@ -1678,17 +2537,15 @@ static void wsrep_RSU_end(THD *thd) int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, const TABLE_LIST* table_list) { - int ret= 0; - /* No isolation for applier or replaying threads. */ - if (thd->wsrep_exec_mode == REPL_RECV) - return 0; + if (thd->wsrep_exec_mode == REPL_RECV) return 0; - mysql_mutex_lock(&thd->LOCK_thd_data); + int ret= 0; + mysql_mutex_lock(&thd->LOCK_wsrep_thd); - if (thd->wsrep_conflict_state == MUST_ABORT) + if (thd->wsrep_conflict_state() == MUST_ABORT) { WSREP_INFO("thread: %lld schema: %s query: %s has been aborted due to multi-master conflict", (longlong) thd->thread_id, thd->get_db(), thd->query()); @@ -1703,14 +2560,14 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, if (thd->global_read_lock.can_acquire_protection()) { WSREP_DEBUG("Aborting TOI: Global Read-Lock (FTWRL) in place: %s %lld", - thd->query(), (longlong) thd->thread_id); + WSREP_QUERY(thd), thd->thread_id); return -1; } if (wsrep_debug && thd->mdl_context.has_locks()) { WSREP_DEBUG("thread holds MDL locks at TI begin: %s %lld", - thd->query(), (longlong) thd->thread_id); + WSREP_QUERY(thd), thd->thread_id); } /* @@ -1730,10 +2587,11 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, { switch (thd->variables.wsrep_OSU_method) { case WSREP_OSU_TOI: - ret = wsrep_TOI_begin(thd, db_, table_, table_list); + case WSREP_OSU_NBO: + ret= wsrep_TOI_begin(thd, db_, table_, table_list); break; case WSREP_OSU_RSU: - ret = wsrep_RSU_begin(thd, db_, table_); + ret= wsrep_RSU_begin(thd, db_, table_); break; default: WSREP_ERROR("Unsupported OSU method: %lu", @@ -1761,29 +2619,126 @@ void wsrep_to_isolation_end(THD *thd) { switch(thd->variables.wsrep_OSU_method) { - case WSREP_OSU_TOI: wsrep_TOI_end(thd); break; - case WSREP_OSU_RSU: wsrep_RSU_end(thd); break; + case WSREP_OSU_TOI: + case WSREP_OSU_NBO: + wsrep_TOI_end(thd); + break; + case WSREP_OSU_RSU: + wsrep_RSU_end(thd); + break; default: WSREP_WARN("Unsupported wsrep OSU method at isolation end: %lu", thd->variables.wsrep_OSU_method); break; } + mysql_mutex_lock(&thd->LOCK_wsrep_thd); wsrep_cleanup_transaction(thd); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } +} + +void wsrep_begin_nbo_unlock(THD* thd) +{ + DBUG_ASSERT(thd->wsrep_nbo_ctx); + if (thd->wsrep_exec_mode == TOTAL_ORDER) + { + if (wsrep->to_execute_end(wsrep, thd->thread_id, NULL) != WSREP_OK) { + WSREP_ERROR("Non-blocking operation failed to release provider " + "resources, cannot continue"); + unireg_abort(1); + } + } + else if (thd->wsrep_exec_mode == REPL_RECV) { + thd->wsrep_nbo_ctx->signal(); } + thd->wsrep_nbo_ctx->set_toi_released(true); +} + +void wsrep_end_nbo_lock(THD* thd, const TABLE_LIST *table_list) +{ + DBUG_ASSERT(thd->wsrep_nbo_ctx); + + // Release TOI critical section if not released yet. This + // may happen if operation fails in early phase. + if (thd->wsrep_nbo_ctx->toi_released() == false) { + wsrep_begin_nbo_unlock(thd); + } + + DBUG_ASSERT(thd->wsrep_exec_mode == TOTAL_ORDER || + thd->wsrep_exec_mode == REPL_RECV); + wsrep_status_t ret; + uint32_t flags= WSREP_FLAG_TRX_END; + + wsrep_key_arr_t key_arr= {0, 0}; + + if (wsrep_prepare_keys_for_isolation(thd, NULL, NULL, table_list, &key_arr)) + { + WSREP_ERROR("Failed to prepare keys for NBO end. This is fatal, must abort"); + unireg_abort(1); + + } + thd_proc_info(thd, "acquiring total order isolation for NBO end"); + + DBUG_ASSERT(key_arr.keys_len > 0); + + time_t wait_start= time(NULL); + while ((ret= wsrep->to_execute_start(wsrep, thd->thread_id, + key_arr.keys, key_arr.keys_len, 0, 0, + flags, + &thd->wsrep_trx_meta)) + == WSREP_CONN_FAIL) { + if (thd->killed != NOT_KILLED) { + WSREP_ERROR("Non-blocking operation end failed to sync with group, " + "thd killed %d", thd->killed); + /* Error handling happens outside of while() */ + break; + } + usleep(100000); + if (ulong(time(NULL) - wait_start) >= thd->variables.lock_wait_timeout) + { + WSREP_ERROR("Lock wait timeout while waiting NBO end to replicate."); + break; + } + } + + if (ret != WSREP_OK) + { + WSREP_ERROR("Failed to acquire total order isolation for non-blocking DDL " + "end event, provider returned error code %d: " + "(schema: %s, query: %s)", + ret, (thd->db.str ? thd->db.str : "(null)"), + WSREP_QUERY(thd)); + thd->get_stmt_da()->set_overwrite_status(true); + my_error(ER_ERROR_DURING_COMMIT, MYF(0), ret); + thd->get_stmt_da()->set_overwrite_status(false); + WSREP_ERROR("This will leave database in inconsistent state since DDL " + "execution cannot be terminated in order. Node must rejoin " + "the cluster via SST"); + wsrep->free_connection(wsrep, thd->thread_id); + wsrep->disconnect(wsrep); + // We let the operation to finish out of order in order to release + // all resources properly. However GTID is cleared so that the + // event won't be binlogged with incorrect GTID. + thd->wsrep_trx_meta.gtid= WSREP_GTID_UNDEFINED; + } + + thd->wsrep_nbo_ctx->set_toi_released(false); } #define WSREP_MDL_LOG(severity, msg, schema, schema_len, req, gra) \ WSREP_##severity( \ "%s\n" \ "schema: %.*s\n" \ - "request: (%lld \tseqno %lld \twsrep (%d, %d, %d) cmd %d %d \t%s)\n" \ - "granted: (%lld \tseqno %lld \twsrep (%d, %d, %d) cmd %d %d \t%s)", \ + "request: (%lld \tseqno %lld \twsrep (%d, %d, %d) cmd %d %d \t%s)\n" \ + "granted: (%lld \tseqno %lld \twsrep (%d, %d, %d) cmd %d %d \t%s)", \ msg, schema_len, schema, \ - (longlong) req->thread_id, (long long)wsrep_thd_trx_seqno(req), \ - req->wsrep_exec_mode, req->wsrep_query_state, req->wsrep_conflict_state, \ + (longlong) req->thread_id, (long long)wsrep_thd_trx_seqno(req), \ + req->wsrep_exec_mode, req->wsrep_query_state_unsafe(), \ + req->wsrep_conflict_state_unsafe(), \ req->get_command(), req->lex->sql_command, req->query(), \ - (longlong) gra->thread_id, (long long)wsrep_thd_trx_seqno(gra), \ - gra->wsrep_exec_mode, gra->wsrep_query_state, gra->wsrep_conflict_state, \ + (longlong) gra->thread_id, (long long)wsrep_thd_trx_seqno(gra), \ + gra->wsrep_exec_mode, gra->wsrep_query_state_unsafe(), \ + gra->wsrep_conflict_state_unsafe(), \ gra->get_command(), gra->lex->sql_command, gra->query()); /** @@ -1810,8 +2765,6 @@ bool wsrep_grant_mdl_exception(MDL_context *requestor_ctx, const char* schema= key->db_name(); int schema_len= key->db_name_length(); - mysql_mutex_lock(&request_thd->LOCK_thd_data); - /* We consider granting MDL exceptions only for appliers (BF THD) and ones executing under TOI mode. @@ -1831,9 +2784,10 @@ bool wsrep_grant_mdl_exception(MDL_context *requestor_ctx, lock is not granted to the requester THD, thus it has to wait. @return false */ + mysql_mutex_lock(&request_thd->LOCK_wsrep_thd); if (request_thd->wsrep_exec_mode == TOTAL_ORDER || - request_thd->wsrep_exec_mode == REPL_RECV) - { + request_thd->wsrep_exec_mode == REPL_RECV) { + mysql_mutex_unlock(&request_thd->LOCK_thd_data); WSREP_MDL_LOG(DEBUG, "MDL conflict ", schema, schema_len, request_thd, granted_thd); @@ -1843,11 +2797,23 @@ bool wsrep_grant_mdl_exception(MDL_context *requestor_ctx, if (granted_thd->wsrep_exec_mode == TOTAL_ORDER || granted_thd->wsrep_exec_mode == REPL_RECV) { - WSREP_MDL_LOG(INFO, "MDL BF-BF conflict", schema, schema_len, - request_thd, granted_thd); - ticket->wsrep_report(true); - mysql_mutex_unlock(&granted_thd->LOCK_thd_data); - ret= true; + if (wsrep_thd_is_SR((void*)granted_thd) && + !wsrep_thd_is_SR((void*)request_thd)) + { + WSREP_MDL_LOG(INFO, "MDL conflict, DDL vs SR", + schema, schema_len, request_thd, granted_thd); + mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); + wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); + ret = FALSE; + } + else + { + WSREP_MDL_LOG(INFO, "MDL BF-BF conflict", schema, schema_len, + request_thd, granted_thd); + ticket->wsrep_report(true); + mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); + ret = TRUE; + } } else if (granted_thd->lex->sql_command == SQLCOM_FLUSH || granted_thd->mdl_context.has_explicit_locks()) @@ -1855,52 +2821,173 @@ bool wsrep_grant_mdl_exception(MDL_context *requestor_ctx, WSREP_DEBUG("BF thread waiting for FLUSH"); ticket->wsrep_report(wsrep_debug); mysql_mutex_unlock(&granted_thd->LOCK_thd_data); - ret= false; + ret = FALSE; + } + else if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE) + { + WSREP_DEBUG("DROP caused BF abort"); + ticket->wsrep_report(wsrep_debug); + mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); + wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); + ret = FALSE; + } + else if (granted_thd->wsrep_query_state() == QUERY_COMMITTING) + { + WSREP_DEBUG("mdl granted, but commiting thd abort scheduled"); + ticket->wsrep_report(wsrep_debug); + mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); + wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); + ret = FALSE; } else { - /* Print some debug information. */ - if (wsrep_debug) + WSREP_MDL_LOG(DEBUG, "MDL conflict-> BF abort", schema, schema_len, + request_thd, granted_thd); + ticket->wsrep_report(wsrep_debug); + //if (granted_thd->wsrep_conflict_state == CERT_FAILURE) + switch (granted_thd->wsrep_conflict_state()) { - if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE || - request_thd->lex->sql_command == SQLCOM_DROP_SEQUENCE) - { - WSREP_DEBUG("DROP caused BF abort, conf %d", granted_thd->wsrep_conflict_state); - } - else if (granted_thd->wsrep_query_state == QUERY_COMMITTING) - { - WSREP_DEBUG("MDL granted, but committing thd abort scheduled"); - } - else - { - WSREP_MDL_LOG(DEBUG, "MDL conflict-> BF abort", schema, schema_len, - request_thd, granted_thd); - } - ticket->wsrep_report(true); + case CERT_FAILURE: + { + WSREP_DEBUG("MDL granted is aborting because of cert failure"); + sleep(20); + mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); + ret = TRUE; + break; + } + case ABORTING: + { + WSREP_DEBUG("MDL granted is aborting %d", + granted_thd->wsrep_conflict_state()); + mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); + ret = TRUE; + break; + } + case MUST_ABORT: + case ABORTED: + case MUST_REPLAY: + case REPLAYING: + case RETRY_AUTOCOMMIT: + WSREP_DEBUG("MDL granted is in %d state", + granted_thd->wsrep_conflict_state()); + // fall through + case NO_CONFLICT: + { + mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); + wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); + ret = FALSE; + break; + } } - - mysql_mutex_unlock(&granted_thd->LOCK_thd_data); - wsrep_abort_thd((void *) request_thd, (void *) granted_thd, 1); - ret= false; } } else { mysql_mutex_unlock(&request_thd->LOCK_thd_data); } - return ret; } +void +wsrep_last_committed_id(wsrep_gtid_t* gtid) +{ + wsrep->last_committed_id(wsrep, gtid); +} + +void +wsrep_node_uuid(wsrep_uuid_t& uuid) +{ + uuid = node_uuid; +} + +bool wsrep_node_is_donor() +{ + return (WSREP_ON) ? (local_status.get() == 2) : false; +} + +bool wsrep_node_is_synced() +{ + return (WSREP_ON) ? (local_status.get() == 4) : false; +} + +int wsrep_must_ignore_error(THD* thd) +{ + const int error= thd->get_stmt_da()->sql_errno(); + const uint flags= sql_command_flags[thd->lex->sql_command]; + + DBUG_ASSERT(error); + DBUG_ASSERT((thd->wsrep_exec_mode == TOTAL_ORDER) || + (thd->wsrep_exec_mode == REPL_RECV && thd->wsrep_apply_toi)); + + if ((wsrep_ignore_apply_errors & WSREP_IGNORE_ERRORS_ON_DDL)) + goto ignore_error; + + if ((flags & CF_WSREP_MAY_IGNORE_ERRORS) && + (wsrep_ignore_apply_errors & WSREP_IGNORE_ERRORS_ON_RECONCILING_DDL)) + { + switch (error) + { + case ER_DB_DROP_EXISTS: + case ER_BAD_TABLE_ERROR: + case ER_CANT_DROP_FIELD_OR_KEY: + goto ignore_error; + } + } + + return 0; + +ignore_error: + WSREP_WARN("Ignoring error '%s' on query. " + "Default database: '%s'. Query: '%s', Error_code: %d", + thd->get_stmt_da()->message(), + print_slave_db_safe(thd->db.str), + thd->query(), + error); + return 1; +} + +int wsrep_ignored_error_code(Log_event* ev, int error) +{ + const THD* thd= ev->thd; + + DBUG_ASSERT(error); + DBUG_ASSERT(thd->wsrep_exec_mode == REPL_RECV && !thd->wsrep_apply_toi); + + if ((wsrep_ignore_apply_errors & WSREP_IGNORE_ERRORS_ON_RECONCILING_DML)) + { + const int ev_type= ev->get_type_code(); + if (ev_type == DELETE_ROWS_EVENT && error == ER_KEY_NOT_FOUND) + goto ignore_error; + } -pthread_handler_t start_wsrep_THD(void *arg) + return 0; + +ignore_error: + WSREP_WARN("Ignoring error '%s' on %s event. Error_code: %d", + thd->get_stmt_da()->message(), + ev->get_type_str(), + error); + return 1; +} + +void *start_wsrep_THD(void *arg) { THD *thd; - wsrep_thd_processor_fun processor= (wsrep_thd_processor_fun)arg; + // wsrep_thd_processor_fun processor= (wsrep_thd_processor_fun)arg; - if (my_thread_init() || (!(thd= new THD(next_thread_id(), true)))) + Wsrep_thd_args* thd_args= (Wsrep_thd_args*) arg; + + if (my_thread_init()) { - goto error; + WSREP_ERROR("Could not initialize thread"); + delete thd_args; + return(NULL); + } + + if (!(thd= new THD(next_thread_id(), true))) + { + delete thd_args; + return(NULL); } mysql_mutex_lock(&LOCK_thread_count); @@ -1918,6 +3005,7 @@ pthread_handler_t start_wsrep_THD(void *arg) my_net_init(&thd->net,(st_vio*) 0, thd, MYF(0)); DBUG_PRINT("wsrep",(("creating thread %lld"), (long long)thd->thread_id)); + WSREP_DEBUG("Creating wsrep system thread: %lld", thd->thread_id); thd->prior_thr_create_utime= thd->start_utime= microsecond_interval_timer(); (void) mysql_mutex_unlock(&LOCK_thread_count); @@ -1936,6 +3024,7 @@ pthread_handler_t start_wsrep_THD(void *arg) close_connection(thd, ER_OUT_OF_RESOURCES); statistic_increment(aborted_connects,&LOCK_status); MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); + delete thd_args; goto error; } @@ -1958,6 +3047,8 @@ pthread_handler_t start_wsrep_THD(void *arg) close_connection(thd, ER_OUT_OF_RESOURCES); statistic_increment(aborted_connects,&LOCK_status); MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); + delete thd; + delete thd_args; goto error; } @@ -1975,10 +3066,14 @@ pthread_handler_t start_wsrep_THD(void *arg) mysql_cond_broadcast(&COND_thread_count); mysql_mutex_unlock(&LOCK_thread_count); - processor(thd); + thd_args->fun()(thd, thd_args->args()); + thd->store_globals(); + + WSREP_DEBUG("wsrep system thread: %lld closing", thd->thread_id); close_connection(thd, 0); - + delete thd_args; + mysql_mutex_lock(&LOCK_thread_count); wsrep_running_threads--; WSREP_DEBUG("wsrep running threads now: %lu", wsrep_running_threads); @@ -2021,13 +3116,19 @@ error: static bool abort_replicated(THD *thd) { bool ret_code= false; - if (thd->wsrep_query_state== QUERY_COMMITTING) + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_query_state()== QUERY_COMMITTING) { WSREP_DEBUG("aborting replicated trx: %llu", (ulonglong)(thd->real_id)); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); (void)wsrep_abort_thd(thd, thd, TRUE); ret_code= true; } + else + { + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } return ret_code; } @@ -2044,7 +3145,7 @@ static inline bool is_replaying_connection(THD *thd) bool ret; mysql_mutex_lock(&thd->LOCK_thd_data); - ret= (thd->wsrep_conflict_state == REPLAYING) ? true : false; + ret= (thd->wsrep_conflict_state() == REPLAYING) ? true : false; mysql_mutex_unlock(&thd->LOCK_thd_data); return ret; @@ -2056,20 +3157,23 @@ static inline bool is_committing_connection(THD *thd) bool ret; mysql_mutex_lock(&thd->LOCK_thd_data); - ret= (thd->wsrep_query_state == QUERY_COMMITTING) ? true : false; + ret= (thd->wsrep_query_state() == QUERY_COMMITTING) ? true : false; mysql_mutex_unlock(&thd->LOCK_thd_data); return ret; } -static bool have_client_connections() +static bool have_client_connections(THD *except_thd) { THD *tmp; I_List_iterator<THD> it(threads); while ((tmp=it++)) { + if (tmp == except_thd) + continue; + DBUG_PRINT("quit",("Informing thread %lld that it's time to die", (longlong) tmp->thread_id)); if (is_client_connection(tmp) && tmp->killed == KILL_CONNECTION) @@ -2085,18 +3189,30 @@ static void wsrep_close_thread(THD *thd) { thd->set_killed(KILL_CONNECTION); MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (thd)); + mysql_mutex_lock(&thd->LOCK_thd_kill); if (thd->mysys_var) { thd->mysys_var->abort=1; mysql_mutex_lock(&thd->mysys_var->mutex); if (thd->mysys_var->current_cond) { - mysql_mutex_lock(thd->mysys_var->current_mutex); - mysql_cond_broadcast(thd->mysys_var->current_cond); - mysql_mutex_unlock(thd->mysys_var->current_mutex); + uint i; + for (i=0; i < 2; i++) + { + int ret= mysql_mutex_trylock(thd->mysys_var->current_mutex); + mysql_cond_broadcast(thd->mysys_var->current_cond); + if (!ret) + { + /* Thread has surely got the signal, unlock and abort */ + mysql_mutex_unlock(thd->mysys_var->current_mutex); + break; + } + sleep(1); + } } mysql_mutex_unlock(&thd->mysys_var->mutex); } + mysql_mutex_unlock(&thd->LOCK_thd_kill); } @@ -2138,46 +3254,64 @@ int wsrep_wait_committing_connections_close(int wait_time) return 0; } - -void wsrep_close_client_connections(my_bool wait_to_end) +void wsrep_close_client_connections(my_bool wait_to_end, THD* except_caller_thd) { - /* - First signal all threads that it's time to die - */ + kill_cached_threads++; + flush_thread_cache(); + + /* OLD ... */ THD *tmp; mysql_mutex_lock(&LOCK_thread_count); // For unlink from list - - bool kill_cached_threads_saved= kill_cached_threads; - kill_cached_threads= true; // prevent future threads caching - mysql_cond_broadcast(&COND_thread_cache); // tell cached threads to die + /* + First signal all threads that it's time to die + */ I_List_iterator<THD> it(threads); while ((tmp=it++)) { DBUG_PRINT("quit",("Informing thread %lld that it's time to die", (longlong) tmp->thread_id)); - /* We skip slave threads & scheduler on this first loop through. */ + /* We skip slave threads, scheduler & caller on this first loop through. */ if (!is_client_connection(tmp)) continue; + if (tmp == except_caller_thd) + { + DBUG_ASSERT(is_client_connection(tmp)); + /* Even though we don't kill the caller we must release resources + * it might have allocated with the provider */ + wsrep_status_t rcode= wsrep->free_connection(wsrep, tmp->thread_id); + if (rcode) { + WSREP_WARN("wsrep failed to free connection context: %lld, code: %d", + tmp->thread_id, rcode); + } + continue; + } + if (is_replaying_connection(tmp)) { + WSREP_DEBUG("killed client was replaying"); tmp->set_killed(KILL_CONNECTION); continue; } /* replicated transactions must be skipped */ if (abort_replicated(tmp)) + { + WSREP_DEBUG("killed client has replicated"); continue; - + } WSREP_DEBUG("closing connection %lld", (longlong) tmp->thread_id); wsrep_close_thread(tmp); } mysql_mutex_unlock(&LOCK_thread_count); - if (thread_count) - sleep(2); // Give threads time to die + /* + Sleep for couple of seconds to give threads time to die. + */ + for (int i= 0; *(volatile int32*) &thread_count && i < 1000; i++) + my_sleep(20000); mysql_mutex_lock(&LOCK_thread_count); /* @@ -2190,7 +3324,8 @@ void wsrep_close_client_connections(my_bool wait_to_end) #ifndef __bsdi__ // Bug in BSDI kernel if (is_client_connection(tmp) && !abort_replicated(tmp) && - !is_replaying_connection(tmp)) + !is_replaying_connection(tmp) && + tmp != except_caller_thd) { WSREP_INFO("killing local connection: %lld", (longlong) tmp->thread_id); close_connection(tmp,0); @@ -2201,14 +3336,14 @@ void wsrep_close_client_connections(my_bool wait_to_end) DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count)); WSREP_DEBUG("waiting for client connections to close: %u", thread_count); - while (wait_to_end && have_client_connections()) + while (wait_to_end && have_client_connections(except_caller_thd)) { - mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); + struct timespec abstime; + set_timespec(abstime, 5); + mysql_cond_timedwait(&COND_thread_count, &LOCK_thread_count, &abstime); DBUG_PRINT("quit",("One thread died (count=%u)", thread_count)); } - kill_cached_threads= kill_cached_threads_saved; - mysql_mutex_unlock(&LOCK_thread_count); /* All client connection threads have now been aborted */ @@ -2247,7 +3382,9 @@ void wsrep_wait_appliers_close(THD *thd) { /* Wait for wsrep appliers to gracefully exit */ mysql_mutex_lock(&LOCK_thread_count); - while (wsrep_running_threads > 1) + while (wsrep_running_threads > 2) + // Rollbacker and post rollbacker threads need to be killed explicitly. + // 1 is for rollbacker thread which needs to be killed explicitly. // This gotta be fixed in a more elegant manner if we gonna have arbitrary // number of non-applier wsrep threads. @@ -2304,7 +3441,7 @@ void wsrep_kill_mysql(THD *thd) } -static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len) +int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len) { String log_query; sp_head *sp = thd->lex->sphead; @@ -2338,13 +3475,15 @@ static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len) } -extern int wsrep_on(THD *thd) +//extern int wsrep_on(THD *thd) +extern int wsrep_on(void *thd_ptr) { + THD* thd = (THD*)thd_ptr; return (int)(WSREP(thd)); } -extern "C" bool wsrep_thd_is_wsrep_on(THD *thd) +bool wsrep_thd_is_wsrep_on(THD *thd) { return thd->variables.wsrep_on; } @@ -2356,22 +3495,15 @@ bool wsrep_consistency_check(THD *thd) } -extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode) +void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode) { thd->wsrep_exec_mode= mode; } -extern "C" void wsrep_thd_set_query_state( - THD *thd, enum wsrep_query_state state) -{ - thd->wsrep_query_state= state; -} - - void wsrep_thd_set_conflict_state(THD *thd, enum wsrep_conflict_state state) { - if (WSREP(thd)) thd->wsrep_conflict_state= state; + if (WSREP(thd)) thd->set_wsrep_conflict_state(state); } @@ -2383,50 +3515,59 @@ enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd) const char *wsrep_thd_exec_mode_str(THD *thd) { - return - (!thd) ? "void" : - (thd->wsrep_exec_mode == LOCAL_STATE) ? "local" : - (thd->wsrep_exec_mode == REPL_RECV) ? "applier" : - (thd->wsrep_exec_mode == TOTAL_ORDER) ? "total order" : - (thd->wsrep_exec_mode == LOCAL_COMMIT) ? "local commit" : "void"; + switch (thd->wsrep_exec_mode) + { + case LOCAL_STATE: return "local"; + case REPL_RECV: return "applier"; + case TOTAL_ORDER: return "total order"; + case LOCAL_COMMIT: return "local commit"; + case LOCAL_ROLLBACK: return "local rollback"; + } + return "void"; + } enum wsrep_query_state wsrep_thd_query_state(THD *thd) { - return thd->wsrep_query_state; + return thd->wsrep_query_state(); } const char *wsrep_thd_query_state_str(THD *thd) { - return - (!thd) ? "void" : - (thd->wsrep_query_state == QUERY_IDLE) ? "idle" : - (thd->wsrep_query_state == QUERY_EXEC) ? "executing" : - (thd->wsrep_query_state == QUERY_COMMITTING) ? "committing" : - (thd->wsrep_query_state == QUERY_EXITING) ? "exiting" : - (thd->wsrep_query_state == QUERY_ROLLINGBACK) ? "rolling back" : "void"; -} + switch (thd->wsrep_query_state_unsafe()) + { + case QUERY_IDLE: return "idle"; + case QUERY_EXEC: return "executing"; + case QUERY_COMMITTING: return "committing"; + case QUERY_ORDERED_COMMIT: return "ordered_commit"; + case QUERY_EXITING: return "exiting"; + } + return "void"; +} enum wsrep_conflict_state wsrep_thd_get_conflict_state(THD *thd) { - return thd->wsrep_conflict_state; + return thd->wsrep_conflict_state(); } const char *wsrep_thd_conflict_state_str(THD *thd) { - return - (!thd) ? "void" : - (thd->wsrep_conflict_state == NO_CONFLICT) ? "no conflict" : - (thd->wsrep_conflict_state == MUST_ABORT) ? "must abort" : - (thd->wsrep_conflict_state == ABORTING) ? "aborting" : - (thd->wsrep_conflict_state == MUST_REPLAY) ? "must replay" : - (thd->wsrep_conflict_state == REPLAYING) ? "replaying" : - (thd->wsrep_conflict_state == RETRY_AUTOCOMMIT) ? "retrying" : - (thd->wsrep_conflict_state == CERT_FAILURE) ? "cert failure" : "void"; + switch (thd->wsrep_conflict_state_unsafe()) + { + case NO_CONFLICT: return "no conflict"; + case MUST_ABORT: return "must abort"; + case ABORTING: return "aborting"; + case ABORTED: return "aborted"; + case MUST_REPLAY: return "must replay"; + case REPLAYING: return "replaying"; + case RETRY_AUTOCOMMIT: return "retrying"; + case CERT_FAILURE: return "cert failure"; + } + return "void"; } @@ -2448,28 +3589,41 @@ void wsrep_thd_UNLOCK(THD *thd) } -extern "C" time_t wsrep_thd_query_start(THD *thd) +time_t wsrep_thd_query_start(THD *thd) { return thd->query_start(); } -extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd) +uint32 wsrep_thd_wsrep_rand(THD *thd) { return thd->wsrep_rand; } -longlong wsrep_thd_trx_seqno(THD *thd) +my_thread_id wsrep_thd_thread_id(THD *thd) +{ + return thd->thread_id; +} + +int64_t wsrep_thd_trx_seqno(const THD *thd) { return (thd) ? thd->wsrep_trx_meta.gtid.seqno : WSREP_SEQNO_UNDEFINED; } -extern "C" query_id_t wsrep_thd_query_id(THD *thd) +query_id_t wsrep_thd_query_id(THD *thd) { return thd->query_id; } +wsrep_trx_id_t wsrep_thd_next_trx_id(THD *thd) +{ + return thd->wsrep_next_trx_id(); +} +wsrep_trx_id_t wsrep_thd_trx_id(THD *thd) +{ + return thd->wsrep_trx_id(); +} char *wsrep_thd_query(THD *thd) { @@ -2477,20 +3631,21 @@ char *wsrep_thd_query(THD *thd) } -extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd) +query_id_t wsrep_thd_wsrep_last_query_id(THD *thd) { return thd->wsrep_last_query_id; } -extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id) +void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id) { thd->wsrep_last_query_id= id; } -extern "C" void wsrep_thd_awake(THD *thd, my_bool signal) +void wsrep_thd_awake(THD *thd, my_bool signal) { + WSREP_DEBUG("wsrep_thd_awake %lu %d", thd->thread_id, signal); if (signal) { thd->awake(KILL_QUERY); @@ -2510,39 +3665,70 @@ int wsrep_thd_retry_counter(THD *thd) } -extern "C" bool wsrep_thd_ignore_table(THD *thd) +bool wsrep_thd_ignore_table(THD *thd) { return thd->wsrep_ignore_table; } extern int +//wsrep_trx_order_before(void *thd1, void *thd2) wsrep_trx_order_before(THD *thd1, THD *thd2) { - if (wsrep_thd_trx_seqno(thd1) < wsrep_thd_trx_seqno(thd2)) { + if (wsrep_thd_trx_seqno((THD*)thd1) < wsrep_thd_trx_seqno((THD*)thd2)) { WSREP_DEBUG("BF conflict, order: %lld %lld\n", - (long long)wsrep_thd_trx_seqno(thd1), - (long long)wsrep_thd_trx_seqno(thd2)); + (long long)wsrep_thd_trx_seqno((THD*)thd1), + (long long)wsrep_thd_trx_seqno((THD*)thd2)); return 1; } WSREP_DEBUG("waiting for BF, trx order: %lld %lld\n", - (long long)wsrep_thd_trx_seqno(thd1), - (long long)wsrep_thd_trx_seqno(thd2)); + (long long)wsrep_thd_trx_seqno((THD*)thd1), + (long long)wsrep_thd_trx_seqno((THD*)thd2)); return 0; } +int +wsrep_trx_is_aborting(THD *thd_ptr) +{ + if (thd_ptr) { + if ((((THD *)thd_ptr)->wsrep_conflict_state() == MUST_ABORT) || + (((THD *)thd_ptr)->wsrep_conflict_state() == ABORTING)) { + return 1; + } + } + return 0; +} -int wsrep_trx_is_aborting(THD *thd_ptr) +void +wsrep_thd_last_written_gtid(THD *thd, wsrep_gtid_t* gtid) { - if (thd_ptr) { - if ((((THD *)thd_ptr)->wsrep_conflict_state == MUST_ABORT) || - (((THD *)thd_ptr)->wsrep_conflict_state == ABORTING)) { - return 1; - } - } - return 0; + *gtid = WSREP_GTID_UNDEFINED; + if (thd) + { + *gtid = thd->wsrep_last_written_gtid; + } } +ulong +wsrep_thd_trx_fragment_size(THD *thd) +{ + if (thd) + return thd->variables.wsrep_trx_fragment_size; + return 0; +} + +bool +wsrep_thd_is_streaming(THD* thd) +{ + return thd && thd->wsrep_is_streaming(); +} + +#if 0 +my_bool wsrep_thd_no_gaps(const void *thd_ptr) +{ + return ((THD*)thd_ptr)->wsrep_no_gaps; +} +#endif // 0 void wsrep_copy_query(THD *thd) { @@ -2614,7 +3800,7 @@ error: } -static int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len) +int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len) { LEX *lex= thd->lex; String stmt_query; @@ -2711,46 +3897,88 @@ my_bool get_wsrep_certify_nonPK() return wsrep_certify_nonPK; } -void wsrep_lock_rollback() +bool wsrep_provider_is_SR_capable() { - mysql_mutex_lock(&LOCK_wsrep_rollback); + return wsrep->capabilities(wsrep) & WSREP_CAP_STREAMING; } -void wsrep_unlock_rollback() -{ - mysql_cond_signal(&COND_wsrep_rollback); - mysql_mutex_unlock(&LOCK_wsrep_rollback); -} -my_bool wsrep_aborting_thd_contains(THD *thd) +int wsrep_ordered_commit_if_no_binlog(THD* thd) { - mysql_mutex_assert_owner(&LOCK_wsrep_rollback); - wsrep_aborting_thd_t abortees = wsrep_aborting_thd; - while (abortees) + return 0; + if (!(wsrep_emulate_bin_log && thd->wsrep_trx_must_order_commit())) { - if (abortees->aborting_thd == thd) - return true; - abortees = abortees->next; + return 0; } - return false; + int ret= 0; + switch (thd->wsrep_exec_mode) + { + case LOCAL_STATE: + case TOTAL_ORDER: + /* Statement commit may get us here */ + break; + case LOCAL_COMMIT: + ret= wsrep_ordered_commit(thd, true, wsrep_apply_error()); + break; + case REPL_RECV: + { + wsrep_buf_t const err= { NULL, 0 }; + wsrep_status_t rcode= + wsrep->commit_order_leave(wsrep, &thd->wsrep_ws_handle, + &thd->wsrep_trx_meta, &err); + if (rcode != WSREP_OK) + { + DBUG_ASSERT(rcode == WSREP_NODE_FAIL); + WSREP_ERROR("Failed to leave commit order critical section (WOKINB), " + "rcode: %d", rcode); + ret= 1; + } + if (!ret) + { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_ORDERED_COMMIT); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } + break; + } + default: + DBUG_ASSERT(0); + WSREP_WARN("Call to wsrep_commit_order_leave_if_no_binlog called in %s", + wsrep_thd_exec_mode_str(thd)); + break; + } + return ret; } -void wsrep_aborting_thd_enqueue(THD *thd) +wsrep_status_t wsrep_tc_log_commit(THD* thd) { - mysql_mutex_assert_owner(&LOCK_wsrep_rollback); - wsrep_aborting_thd_t aborting = (wsrep_aborting_thd_t) - my_malloc(sizeof(struct wsrep_aborting_thd), MYF(0)); - aborting->aborting_thd = thd; - aborting->next = wsrep_aborting_thd; - wsrep_aborting_thd = aborting; -} + if (wsrep_before_commit(thd, true)) + { + return WSREP_TRX_FAIL; + } + if (binlog_hton->commit(binlog_hton, thd, true)) + { + WSREP_ERROR("Binlog hton commit fail"); + return WSREP_TRX_FAIL; + } -bool wsrep_node_is_donor() -{ - return (WSREP_ON) ? (wsrep_config_state->get_status() == 2) : false; -} + if (wsrep_after_commit(thd, true)) + { + return WSREP_TRX_FAIL; + } -bool wsrep_node_is_synced() -{ - return (WSREP_ON) ? (wsrep_config_state->get_status() == 4) : false; + /* Set wsrep transaction id if not set. */ + if (thd->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID) + { + if (thd->wsrep_next_trx_id() == WSREP_UNDEFINED_TRX_ID) + { + thd->set_wsrep_next_trx_id(thd->query_id); + } + DBUG_ASSERT(thd->wsrep_next_trx_id() != WSREP_UNDEFINED_TRX_ID); + + wsrep_ws_handle_for_trx(&thd->wsrep_ws_handle, thd->wsrep_next_trx_id()); + } + DBUG_ASSERT(thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID); + + return WSREP_OK; } diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 699a4daf27a..5145fe86a19 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -1,4 +1,4 @@ -/* Copyright 2008-2015 Codership Oy <http://www.codership.com> +/* Copyright 2008-2017 Codership Oy <http://www.codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,36 +24,28 @@ #ifdef WITH_WSREP typedef struct st_mysql_show_var SHOW_VAR; + #include <sql_priv.h> -//#include "rpl_gtid.h" #include "../wsrep/wsrep_api.h" #include "mdl.h" #include "mysqld.h" #include "sql_table.h" +#include <vector> + #define WSREP_UNDEFINED_TRX_ID ULONGLONG_MAX class set_var; class THD; +typedef std::vector<wsrep_trx_meta_t> wsrep_fragment_set; + enum wsrep_consistency_check_mode { NO_CONSISTENCY_CHECK, CONSISTENCY_CHECK_DECLARED, CONSISTENCY_CHECK_RUNNING, }; -struct wsrep_thd_shadow { - ulonglong options; - uint server_status; - enum wsrep_exec_mode wsrep_exec_mode; - Vio *vio; - ulong tx_isolation; - const char *db; - size_t db_length; - my_hrtime_t user_time; - longlong row_count_func; -}; - // Global wsrep parameters extern wsrep_t* wsrep; @@ -77,7 +69,6 @@ extern const char* wsrep_start_position; extern ulong wsrep_max_ws_size; extern ulong wsrep_max_ws_rows; extern const char* wsrep_notify_cmd; -extern long wsrep_max_protocol_version; extern ulong wsrep_forced_binlog_format; extern my_bool wsrep_desync; extern ulong wsrep_reject_queries; @@ -87,6 +78,10 @@ extern my_bool wsrep_restart_slave; extern my_bool wsrep_restart_slave_activated; extern my_bool wsrep_slave_FK_checks; extern my_bool wsrep_slave_UK_checks; +extern ulong wsrep_trx_fragment_size; +extern ulong wsrep_trx_fragment_unit; +extern ulong wsrep_SR_store_type; +extern uint wsrep_ignore_apply_errors; extern ulong wsrep_running_threads; extern bool wsrep_new_cluster; extern bool wsrep_gtid_mode; @@ -101,6 +96,7 @@ enum enum_wsrep_reject_types { enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU, + WSREP_OSU_NBO, WSREP_OSU_NONE, }; @@ -114,6 +110,14 @@ enum enum_wsrep_sync_wait { WSREP_SYNC_WAIT_MAX = 0xF }; +enum enum_wsrep_ignore_apply_error { + WSREP_IGNORE_ERRORS_NONE = 0x0, + WSREP_IGNORE_ERRORS_ON_RECONCILING_DDL = 0x1, + WSREP_IGNORE_ERRORS_ON_RECONCILING_DML = 0x2, + WSREP_IGNORE_ERRORS_ON_DDL = 0x4, + WSREP_IGNORE_ERRORS_MAX = 0x7 +}; + // MySQL status variables extern my_bool wsrep_connected; extern my_bool wsrep_ready; @@ -126,9 +130,12 @@ extern long long wsrep_local_bf_aborts; extern const char* wsrep_provider_name; extern const char* wsrep_provider_version; extern const char* wsrep_provider_vendor; +extern char* wsrep_provider_capabilities; +extern char* wsrep_cluster_capabilities; -int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope); +int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff); +int wsrep_show_ready(THD *thd, SHOW_VAR *var, char *buff); +void wsrep_free_status(THD *thd); int wsrep_init(); void wsrep_deinit(bool free_options); @@ -147,37 +154,47 @@ void wsrep_init_startup(bool before); // Other wsrep global variables extern my_bool wsrep_inited; // whether wsrep is initialized ? - -extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode); -extern "C" void wsrep_thd_set_query_state( - THD *thd, enum wsrep_query_state state); - extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id); - +extern "C" void wsrep_fire_rollbacker(THD *thd); extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd); extern "C" time_t wsrep_thd_query_start(THD *thd); extern "C" query_id_t wsrep_thd_query_id(THD *thd); +extern "C" wsrep_trx_id_t wsrep_thd_next_trx_id(THD *thd); +extern "C" wsrep_trx_id_t wsrep_thd_trx_id(THD *thd); extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd); extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id); -extern void wsrep_close_client_connections(my_bool wait_to_end); +extern "C" void wsrep_thd_last_written_gtid(THD *thd, wsrep_gtid_t *t); +extern "C" ulong wsrep_thd_trx_fragment_size(THD *thd); + extern int wsrep_wait_committing_connections_close(int wait_time); extern void wsrep_close_applier(THD *thd); extern void wsrep_wait_appliers_close(THD *thd); extern void wsrep_close_applier_threads(int count); extern void wsrep_kill_mysql(THD *thd); + /* new defines */ extern void wsrep_stop_replication(THD *thd); extern bool wsrep_start_replication(); +extern void wsrep_shutdown_replication(); extern bool wsrep_must_sync_wait(THD* thd, uint mask = WSREP_SYNC_WAIT_BEFORE_READ); extern bool wsrep_sync_wait(THD* thd, uint mask = WSREP_SYNC_WAIT_BEFORE_READ); +extern wsrep_status_t wsrep_sync_wait_upto (THD* thd, wsrep_gtid_t* upto, int timeout); +extern void wsrep_last_committed_id (wsrep_gtid_t* gtid); extern int wsrep_check_opts(); extern void wsrep_prepend_PATH (const char* path); + + /* Other global variables */ extern wsrep_seqno_t wsrep_locked_seqno; +/* use xxxxxx_NNULL macros when thd pointer is guaranteed to be non-null to + * avoid compiler warnings (GCC 6 and later) */ +#define WSREP_NNULL(thd) \ + (WSREP_ON && wsrep && thd->variables.wsrep_on) + #define WSREP_ON \ (global_system_variables.wsrep_on) @@ -186,12 +203,22 @@ extern wsrep_seqno_t wsrep_locked_seqno; wsrep_provider && \ strcmp(wsrep_provider, WSREP_NONE)) +#define WSREP_NOT_SPECIFIED \ + (strlen(wsrep_provider)== 0 || \ + !strcmp(wsrep_provider, WSREP_NONE)) + #define WSREP(thd) \ - (WSREP_ON && thd->variables.wsrep_on) + (thd && WSREP_NNULL(thd)) + +#define WSREP_CLIENT_NNULL(thd) \ + (WSREP_NNULL(thd) && thd->wsrep_client_thread) #define WSREP_CLIENT(thd) \ (WSREP(thd) && thd->wsrep_client_thread) +#define WSREP_EMULATE_BINLOG_NNULL(thd) \ + (WSREP_NNULL(thd) && wsrep_emulate_bin_log) + #define WSREP_EMULATE_BINLOG(thd) \ (WSREP(thd) && wsrep_emulate_bin_log) @@ -205,9 +232,9 @@ void wsrep_log(void (*fun)(const char *, ...), const char *format, ...); #define WSREP_LOG_CONFLICT_THD(thd, role) \ WSREP_LOG(sql_print_information, \ "%s: \n " \ - " THD: %lu, mode: %s, state: %s, conflict: %s, seqno: %lld\n " \ + " THD: %lld, mode: %s, state: %s, conflict: %s, seqno: %lld\n " \ " SQL: %s", \ - role, thd_get_thread_id(thd), wsrep_thd_exec_mode_str(thd), \ + role, wsrep_thd_thread_id(thd), wsrep_thd_exec_mode_str(thd), \ wsrep_thd_query_state_str(thd), \ wsrep_thd_conflict_state_str(thd), (long long)wsrep_thd_trx_seqno(thd), \ wsrep_thd_query(thd) \ @@ -221,6 +248,7 @@ void wsrep_log(void (*fun)(const char *, ...), const char *format, ...); ); \ if (bf_thd != NULL) WSREP_LOG_CONFLICT_THD(bf_thd, "Winning thread"); \ if (victim_thd) WSREP_LOG_CONFLICT_THD(victim_thd, "Victim thread"); \ + WSREP_LOG(sql_print_information, "context: %s:%d", __FILE__, __LINE__); \ } #define WSREP_PROVIDER_EXISTS \ @@ -231,33 +259,45 @@ void wsrep_log(void (*fun)(const char *, ...), const char *format, ...); extern my_bool wsrep_ready_get(); extern void wsrep_ready_wait(); +static inline +wsrep_status_t wsrep_trx_status_to_wsrep_status(wsrep_trx_status status) +{ + switch (status) + { + case WSREP_TRX_OK: + return WSREP_OK; + case WSREP_TRX_CERT_FAIL: + case WSREP_TRX_ERROR: + return WSREP_TRX_FAIL; + case WSREP_TRX_SIZE_EXCEEDED: + return WSREP_SIZE_EXCEEDED; + } + return WSREP_NOT_IMPLEMENTED; +} + class Ha_trx_info; struct THD_TRANS; void wsrep_register_hton(THD* thd, bool all); +void wsrep_register_hton(THD* thd, bool all, bool force); +void wsrep_post_rollback(THD* thd); void wsrep_brute_force_killer(THD *thd); int wsrep_hire_brute_force_killer(THD *thd, uint64_t trx_id); -/* this is visible for client build so that innodb plugin gets this */ -typedef struct wsrep_aborting_thd { - struct wsrep_aborting_thd *next; - THD *aborting_thd; -} *wsrep_aborting_thd_t; - extern mysql_mutex_t LOCK_wsrep_ready; extern mysql_cond_t COND_wsrep_ready; extern mysql_mutex_t LOCK_wsrep_sst; extern mysql_cond_t COND_wsrep_sst; extern mysql_mutex_t LOCK_wsrep_sst_init; extern mysql_cond_t COND_wsrep_sst_init; -extern mysql_mutex_t LOCK_wsrep_rollback; -extern mysql_cond_t COND_wsrep_rollback; extern int wsrep_replaying; extern mysql_mutex_t LOCK_wsrep_replaying; extern mysql_cond_t COND_wsrep_replaying; extern mysql_mutex_t LOCK_wsrep_slave_threads; extern mysql_mutex_t LOCK_wsrep_desync; +extern mysql_mutex_t LOCK_wsrep_SR_pool; +extern mysql_mutex_t LOCK_wsrep_SR_store; +extern mysql_mutex_t LOCK_wsrep_thd_pool; extern mysql_mutex_t LOCK_wsrep_config_state; -extern wsrep_aborting_thd_t wsrep_aborting_thd; extern my_bool wsrep_emulate_bin_log; extern int wsrep_to_isolation; #ifdef GTID_SUPPORT @@ -267,6 +307,9 @@ extern my_bool wsrep_preordered_opt; extern handlerton *wsrep_hton; #ifdef HAVE_PSI_INTERFACE + +extern PSI_mutex_key key_LOCK_wsrep_thd; +extern PSI_cond_key key_COND_wsrep_thd; extern PSI_mutex_key key_LOCK_wsrep_ready; extern PSI_mutex_key key_COND_wsrep_ready; extern PSI_mutex_key key_LOCK_wsrep_sst; @@ -275,24 +318,161 @@ extern PSI_mutex_key key_LOCK_wsrep_sst_init; extern PSI_cond_key key_COND_wsrep_sst_init; extern PSI_mutex_key key_LOCK_wsrep_sst_thread; extern PSI_cond_key key_COND_wsrep_sst_thread; -extern PSI_mutex_key key_LOCK_wsrep_rollback; -extern PSI_cond_key key_COND_wsrep_rollback; extern PSI_mutex_key key_LOCK_wsrep_replaying; extern PSI_cond_key key_COND_wsrep_replaying; extern PSI_mutex_key key_LOCK_wsrep_slave_threads; extern PSI_mutex_key key_LOCK_wsrep_desync; +extern PSI_mutex_key key_LOCK_wsrep_SR_pool; +extern PSI_mutex_key key_LOCK_wsrep_SR_store; +extern PSI_mutex_key key_LOCK_wsrep_thd_pool; +extern PSI_mutex_key key_LOCK_wsrep_nbo; +extern PSI_cond_key key_COND_wsrep_nbo; +extern PSI_mutex_key key_LOCK_wsrep_global_seqno; +extern PSI_mutex_key key_LOCK_wsrep_thd_queue; +extern PSI_cond_key key_COND_wsrep_thd_queue; extern PSI_file_key key_file_wsrep_gra_log; #endif /* HAVE_PSI_INTERFACE */ struct TABLE_LIST; int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, const TABLE_LIST* table_list); + +void wsrep_begin_nbo_unlock(THD*); +void wsrep_end_nbo_lock(THD*, const TABLE_LIST *table_list); + void wsrep_to_isolation_end(THD *thd); + void wsrep_cleanup_transaction(THD *thd); +bool wsrep_append_SR_keys(THD *thd); int wsrep_to_buf_helper( THD* thd, const char *query, uint query_len, uchar** buf, size_t* buf_len); +int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len); +int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len); int wsrep_create_event_query(THD *thd, uchar** buf, size_t* buf_len); +bool wsrep_stmt_rollback_is_safe(THD* thd); + +void wsrep_init_sidno(const wsrep_uuid_t&); +bool wsrep_node_is_donor(); +bool wsrep_node_is_synced(); + +void wsrep_init_schema(); +void wsrep_init_SR(); +void wsrep_verify_SE_checkpoint(const wsrep_uuid_t& uuid, wsrep_seqno_t seqno); +int wsrep_replay_from_SR_store(THD*, const wsrep_trx_meta_t&); +void wsrep_node_uuid(wsrep_uuid_t&); + +class Log_event; +int wsrep_ignored_error_code(Log_event* ev, int error); +int wsrep_must_ignore_error(THD* thd); + +bool wsrep_replicate_GTID(THD* thd); + +/* + * Helper class for non-blocking operations. + */ +class Wsrep_nbo_ctx +{ + public: + Wsrep_nbo_ctx(const void* buf, size_t buf_len, + uint32_t flags, const wsrep_trx_meta_t& meta) : + buf_ (0), + buf_len_(buf_len), + flags_ (flags), + meta_ (meta), + mutex_ (), + cond_ (), + ready_ (false), + executing_(false), + toi_released_(false) + { + mysql_mutex_init(key_LOCK_wsrep_nbo, &mutex_, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_wsrep_nbo, &cond_, NULL); + + if ((buf_ = malloc(buf_len_)) == 0) { + throw std::exception(); + } + memcpy(buf_, buf, buf_len); + } + + + ~Wsrep_nbo_ctx() { + free(buf_); + } + + const void* buf() { return buf_; } + size_t buf_len() { return buf_len_; } + uint32_t flags() { return flags_; } + const wsrep_trx_meta_t& meta() { return meta_; } + + void wait_sync() + { + mysql_mutex_lock(&mutex_); + while (ready_ == false) + { + mysql_cond_wait(&cond_, &mutex_); + } + mysql_mutex_unlock(&mutex_); + } + + void signal() + { + mysql_mutex_lock(&mutex_); + ready_ = true; + mysql_cond_signal(&cond_); + mysql_mutex_unlock(&mutex_); + } + + bool ready() const { return ready_; } + + void set_executing(bool val) { executing_ = val; } + + bool executing() const { return executing_; } + + void set_toi_released(bool val) { toi_released_ = true; } + + bool toi_released() const { return toi_released_; } + + private: + void* buf_; + size_t buf_len_; + uint32_t flags_; + wsrep_trx_meta_t meta_; + mysql_mutex_t mutex_; + mysql_cond_t cond_; + bool ready_; + bool executing_; + bool toi_released_; +}; + +/* + Convenience macros for determining NBO start and END +*/ +#define WSREP_NBO_START(flags_) \ +((flags_ & WSREP_FLAG_ISOLATION) && (flags_ & WSREP_FLAG_TRX_START) && \ + !(flags_ & WSREP_FLAG_TRX_END)) + +#define WSREP_NBO_END(flags_) \ + ((flags_ & WSREP_FLAG_ISOLATION) && !(flags_ & WSREP_FLAG_TRX_START) && \ + (flags_ & WSREP_FLAG_TRX_END)) + +#define WSREP_TOI(flags_) \ + ((flags_ & WSREP_FLAG_ISOLATION) && (flags_ & WSREP_FLAG_TRX_START) && \ + (flags_ & WSREP_FLAG_TRX_END)) + +typedef struct wsrep_key_arr +{ + wsrep_key_t* keys; + size_t keys_len; +} wsrep_key_arr_t; + +bool wsrep_prepare_keys_for_isolation(THD* thd, + const char* db, + const char* table, + const TABLE_LIST* table_list, + wsrep_key_arr_t* ka); +void wsrep_keys_free(wsrep_key_arr_t* key_arr); + extern bool wsrep_grant_mdl_exception(MDL_context *requestor_ctx, MDL_ticket *ticket, @@ -303,10 +483,34 @@ void thd_binlog_flush_pending_rows_event(THD *thd, bool stmt_end); void thd_binlog_rollback_stmt(THD * thd); void thd_binlog_trx_reset(THD * thd); -typedef void (*wsrep_thd_processor_fun)(THD *); -pthread_handler_t start_wsrep_THD(void *arg); +typedef void (*wsrep_thd_processor_fun)(THD*, void *); +class Wsrep_thd_args +{ + public: + Wsrep_thd_args(wsrep_thd_processor_fun fun, void* args) + : + fun_ (fun), + args_(args) + { } + + wsrep_thd_processor_fun fun() { return fun_; } + + void* args() { return args_; } + + private: + + Wsrep_thd_args(const Wsrep_thd_args&); + Wsrep_thd_args& operator=(const Wsrep_thd_args&); + + wsrep_thd_processor_fun fun_; + void* args_; +}; + +void* start_wsrep_THD(void*); + +extern void wsrep_close_client_connections(my_bool wait_to_end, + THD *except_caller_thd = NULL); int wsrep_wait_committing_connections_close(int wait_time); -void wsrep_close_client_connections(my_bool wait_to_end); void wsrep_close_applier(THD *thd); void wsrep_close_applier_threads(int count); void wsrep_wait_appliers_close(THD *thd); @@ -321,18 +525,6 @@ bool wsrep_create_like_table(THD* thd, TABLE_LIST* table, bool wsrep_node_is_donor(); bool wsrep_node_is_synced(); -typedef struct wsrep_key_arr -{ - wsrep_key_t* keys; - size_t keys_len; -} wsrep_key_arr_t; -bool wsrep_prepare_keys_for_isolation(THD* thd, - const char* db, - const char* table, - const TABLE_LIST* table_list, - wsrep_key_arr_t* ka); -void wsrep_keys_free(wsrep_key_arr_t* key_arr); - #define WSREP_BINLOG_FORMAT(my_format) \ ((wsrep_forced_binlog_format != BINLOG_FORMAT_UNSPEC) ? \ wsrep_forced_binlog_format : my_format) @@ -342,9 +534,11 @@ void wsrep_keys_free(wsrep_key_arr_t* key_arr); #define WSREP(T) (0) #define WSREP_ON (0) #define WSREP_EMULATE_BINLOG(thd) (0) +#define WSREP_EMULATE_BINLOG_NNULL(thd) (0) #define WSREP_CLIENT(thd) (0) #define WSREP_FORMAT(my_format) ((ulong)my_format) #define WSREP_PROVIDER_EXISTS (0) +#define WSREP_NOT_SPECIFIED (1) #define wsrep_emulate_bin_log (0) #define wsrep_to_isolation (0) #define wsrep_init() (1) @@ -367,4 +561,37 @@ void wsrep_keys_free(wsrep_key_arr_t* key_arr); #define wsrep_running_threads (0) #define WSREP_BINLOG_FORMAT(my_format) my_format #endif /* WITH_WSREP */ + +#ifdef WITH_WSREP +/** + * Check if the wsrep provider (ie the Galera library) is capable of + * doing streaming replication. + * @return true if SR capable + */ +bool wsrep_provider_is_SR_capable(); + +/** + * Mark current commit ordered if binlogging is not enabled. + * + * The purpose of this function is to leave commit order critical + * section if binlog is not enabled. + * + * The function can be called from inside storage engine during commit. + * Binlog options are checked inside the function. + * + * @return Zero in case of success, non-zero in case of failure. + */ + +int wsrep_ordered_commit_if_no_binlog(THD*); + +/** + * Commit the current transaction with the + * MySQL "Transaction Coordinator Log" (see `class TC_LOG` in sql/log.h). + * Calling this function will generate and assign a new wsrep transaction id + * for `thd`. + * @return WSREP_OK on success or other WSREP_* error code on failure + */ +wsrep_status_t wsrep_tc_log_commit(THD* thd); + +#endif /* WITH_WSREP */ #endif /* WSREP_MYSQLD_H */ diff --git a/sql/wsrep_plugin.cc b/sql/wsrep_plugin.cc new file mode 100644 index 00000000000..44421075dd4 --- /dev/null +++ b/sql/wsrep_plugin.cc @@ -0,0 +1,53 @@ +/* Copyright 2016 Codership Oy <http://www.codership.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "wsrep_trans_observer.h" +#include "wsrep_mysqld.h" + +#include <mysql/plugin.h> + +static int wsrep_plugin_init(void *p) +{ + WSREP_INFO("wsrep_plugin_init()"); + return wsrep_register_trans_observer(p); +} + +static int wsrep_plugin_deinit(void *p) +{ + WSREP_INFO("wsrep_plugin_deinit()"); + return wsrep_unregister_trans_observer(p); +} + +struct Mysql_replication wsrep_plugin= { + MYSQL_REPLICATION_INTERFACE_VERSION +}; + +mysql_declare_plugin(wsrep) +{ + MYSQL_REPLICATION_PLUGIN, + &wsrep_plugin, + "wsrep", + "Codership Oy", + "Wsrep replication plugin", + PLUGIN_LICENSE_GPL, + wsrep_plugin_init, + wsrep_plugin_deinit, + 0x0100, + NULL, /* Status variables */ + NULL, /* System variables */ + NULL, /* Config options */ + 0 /* Flags */ +} +mysql_declare_plugin_end; diff --git a/sql/wsrep_priv.h b/sql/wsrep_priv.h index 222a49cc2ab..e0206e9377a 100644 --- a/sql/wsrep_priv.h +++ b/sql/wsrep_priv.h @@ -19,6 +19,7 @@ #ifndef WSREP_PRIV_H #define WSREP_PRIV_H +#include <my_global.h> #include "wsrep_mysqld.h" #include "../wsrep/wsrep_api.h" @@ -31,21 +32,23 @@ my_bool wsrep_ready_set (my_bool x); ssize_t wsrep_sst_prepare (void** msg); wsrep_cb_status wsrep_sst_donate_cb (void* app_ctx, void* recv_ctx, - const void* msg, size_t msg_len, + const wsrep_buf_t* msg, const wsrep_gtid_t* state_id, - const char* state, size_t state_len, + const wsrep_buf_t* state, bool bypass); extern wsrep_uuid_t local_uuid; extern wsrep_seqno_t local_seqno; // a helper function -bool wsrep_sst_received (wsrep_t* const wsrep, +void wsrep_sst_received (THD* thd, + wsrep_t* const wsrep, const wsrep_uuid_t& uuid, const wsrep_seqno_t seqno, const void* const state, const size_t state_len, const bool implicit); + /*! SST thread signals init thread about sst completion */ void wsrep_sst_complete(const wsrep_uuid_t*, wsrep_seqno_t, bool); diff --git a/sql/wsrep_schema.cc b/sql/wsrep_schema.cc new file mode 100644 index 00000000000..dd4e13d00ec --- /dev/null +++ b/sql/wsrep_schema.cc @@ -0,0 +1,1481 @@ +/* Copyright (C) 2015-2017 Codership Oy <info@codership.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + +#include "mariadb.h" + +#include "table.h" +#include "key.h" +#include "sql_base.h" +#include "sql_parse.h" +#include "sql_update.h" +#include "transaction.h" + +#include "wsrep_thd_pool.h" +#include "wsrep_schema.h" +#include "wsrep_applier.h" +#include "wsrep_xid.h" + +#include <string> +#include <sstream> + +const std::string wsrep_schema_str= "wsrep_schema"; +static const std::string create_wsrep_schema_str= + "CREATE DATABASE IF NOT EXISTS wsrep_schema"; + +static const std::string create_cluster_table_str= + "CREATE TABLE IF NOT EXISTS wsrep_schema.cluster" + "(" + "cluster_uuid CHAR(36) PRIMARY KEY," + "view_id BIGINT NOT NULL," + "view_seqno BIGINT NOT NULL," + "protocol_version INT NOT NULL" + ") ENGINE=InnoDB"; + +static const std::string create_members_table_str= + "CREATE TABLE IF NOT EXISTS wsrep_schema.members" + "(" + "node_uuid CHAR(36) PRIMARY KEY," + "cluster_uuid CHAR(36) NOT NULL," + "node_name CHAR(32) NOT NULL," + "node_incoming_address VARCHAR(256) NOT NULL" + ") ENGINE=InnoDB"; + +#ifdef WSREP_SCHEMA_MEMBERS_HISTORY +static const std::string create_members_history_table_str= + "CREATE TABLE IF NOT EXISTS wsrep_schema.members_history" + "(" + "node_uuid CHAR(36) PRIMARY KEY," + "cluster_uuid CHAR(36) NOT NULL," + "last_view_id BIGINT NOT NULL," + "last_view_seqno BIGINT NOT NULL," + "node_name CHAR(32) NOT NULL," + "node_incoming_address VARCHAR(256) NOT NULL" + ") ENGINE=InnoDB"; +#endif /* WSREP_SCHEMA_MEMBERS_HISTORY */ + +static const std::string sr_table_str= "SR"; +const std::string sr_table_name_full_str= wsrep_schema_str + "/" + sr_table_str; +static const std::string create_frag_table_str= + "CREATE TABLE IF NOT EXISTS " + wsrep_schema_str + "." + sr_table_str + + "(" + "node_uuid CHAR(36), " + "trx_id BIGINT, " + "seqno BIGINT, " + "flags INT NOT NULL, " + "frag LONGBLOB NOT NULL, " + "PRIMARY KEY (node_uuid, trx_id, seqno)" + ") ENGINE=InnoDB"; + +static const std::string delete_from_cluster_table= + "DELETE FROM wsrep_schema.cluster"; + +static const std::string delete_from_members_table= + "DELETE FROM wsrep_schema.members"; + + +namespace Wsrep_schema_impl +{ + +static int execute_SQL(THD* thd, const char* sql, uint length) { + DBUG_ENTER("Wsrep_schema::execute_SQL()"); + int err= 0; + + PSI_statement_locker *parent_locker= thd->m_statement_psi; + Parser_state parser_state; + + WSREP_DEBUG("SQL: %d %s thd: %lld", length, sql, (long long)thd->thread_id); + + if (parser_state.init(thd, (char*)sql, length) == 0) { + thd->reset_for_next_command(); + lex_start(thd); + + thd->m_statement_psi= NULL; + + thd->set_query((char*)sql, length); + thd->set_query_id(next_query_id()); + + mysql_parse(thd, (char*)sql, length, & parser_state, FALSE, FALSE); + + if (thd->is_error()) { + WSREP_WARN("Wsrep_schema::execute_sql() failed, %d %s\nSQL: %s", + thd->get_stmt_da()->sql_errno(), + thd->get_stmt_da()->message(), + sql); + err= 1; + } + thd->m_statement_psi= parent_locker; + thd->end_statement(); + thd->reset_query(); + close_thread_tables(thd); + delete_explain_query(thd->lex); + } + else { + WSREP_WARN("SR init failure"); + } + thd->cleanup_after_query(); + DBUG_RETURN(err); +} + +/* + Initialize thd for next "statement" + */ +static void init_stmt(THD* thd) { + lex_start(thd); + thd->reset_for_next_command(); +} + +static void finish_stmt(THD* thd) { + trans_commit_stmt(thd); + thd->lex->unit.cleanup(); + 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; + + 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); +#ifdef OUT + tables.init_one_table(schema_name.str, schema_name.length, + table_name.str, table_name.length, + table_name.str, lock_type); +#endif + tables.init_one_table(schema_name, + table_name, + NULL, lock_type); + + if (!open_n_lock_single_table(thd, &tables, tables.lock_type, flags)) { + close_thread_tables(thd); + my_error(ER_NO_SUCH_TABLE, MYF(0), schema_name->str, table_name->str); + DBUG_RETURN(1); + } + + *table= tables.table; + (*table)->use_all_columns(); + + DBUG_RETURN(0); +} + + +static int open_for_write(THD* thd, const char* table_name, TABLE** table) { + // LEX_CSTRING schema_str= { C_STRING_WITH_LEN(wsrep_schema_str.c_str()) }; + 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)) { + 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); + return 0; +} + + +static void store(TABLE* table, uint field, const wsrep_uuid_t& uuid) { + assert(field < table->s->fields); + char uuid_str[37]= {'\0', }; + wsrep_uuid_print(&uuid, uuid_str, sizeof(uuid_str)); + table->field[field]->store(uuid_str, + strlen(uuid_str), + &my_charset_bin); +} + +template <typename INTTYPE> +static void store(TABLE* table, uint field, const INTTYPE val) { + assert(field < table->s->fields); + table->field[field]->store(val); +} + +template <typename CHARTYPE> +static void store(TABLE* table, uint field, const CHARTYPE* str, size_t str_len) { + assert(field < table->s->fields); + table->field[field]->store((const char*)str, + str_len, + &my_charset_bin); +} + +static int update_or_insert(TABLE* table) { + DBUG_ENTER("Wsrep_schema::update_or_insert()"); + int ret= 0; + char* key; + int error; + + /* + Verify that the table has primary key defined. + */ + if (table->s->primary_key >= MAX_KEY || + !table->s->keys_in_use.is_set(table->s->primary_key)) { + WSREP_ERROR("No primary key for %s.%s", + table->s->db.str, table->s->table_name.str); + DBUG_RETURN(1); + } + + /* + Find the record and update or insert a new one if not found. + */ + if (!(key= (char*) my_safe_alloca(table->s->max_unique_length))) { + WSREP_ERROR("Error allocating %ud bytes for key", + table->s->max_unique_length); + DBUG_RETURN(1); + } + + key_copy((uchar*) key, table->record[0], + table->key_info + table->s->primary_key, 0); + + if ((error= table->file->ha_index_read_idx_map(table->record[1], + table->s->primary_key, + (uchar*) key, + HA_WHOLE_KEY, + HA_READ_KEY_EXACT))) { + /* + Row not found, insert a new one. + */ + if ((error= table->file->ha_write_row(table->record[0]))) { + WSREP_ERROR("Error writing into %s.%s: %d", + table->s->db.str, + table->s->table_name.str, + error); + table->file->print_error(error, MYF(0)); + ret= 1; + } + } + else if (!records_are_comparable(table) || compare_record(table)) { + /* + Record has changed + */ + if ((error= table->file->ha_update_row(table->record[1], + table->record[0])) && + error != HA_ERR_RECORD_IS_THE_SAME) { + WSREP_ERROR("Error updating record in %s.%s: %d", + table->s->db.str, + table->s->table_name.str, + error); + table->file->print_error(error, MYF(0)); + ret= 1; + } + } + + my_safe_afree(key, table->s->max_unique_length); + + DBUG_RETURN(ret); +} + +static int insert(TABLE* table) { + DBUG_ENTER("Wsrep_schema::insert()"); + int ret= 0; + int error; + + /* + Verify that the table has primary key defined. + */ + if (table->s->primary_key >= MAX_KEY || + !table->s->keys_in_use.is_set(table->s->primary_key)) { + WSREP_ERROR("No primary key for %s.%s", + table->s->db.str, table->s->table_name.str); + DBUG_RETURN(1); + } + + if ((error= table->file->ha_write_row(table->record[0]))) { + WSREP_ERROR("Error writing into %s.%s: %d", + table->s->db.str, + table->s->table_name.str, + error); + table->file->print_error(error, MYF(0)); + ret= 1; + } + + DBUG_RETURN(ret); +} + +static int delete_row(TABLE* table) { + int error; + int retry= 3; + + do { + error= table->file->ha_delete_row(table->record[0]); + retry--; + } while (error && retry); + + if (error) { + WSREP_ERROR("Error deleting row from %s.%s: %d", + table->s->db.str, + table->s->table_name.str, + error); + table->file->print_error(error, MYF(0)); + return 1; + } + return 0; +} + +static int open_for_read(THD* thd, const char* table_name, TABLE** table) { + // LEX_CSTRING schema_str= { C_STRING_WITH_LEN(wsrep_schema_str.c_str()) }; + + 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)) { + 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); + return 0; +} + +/* + Init table for sequential scan. + + @return 0 in case of success, 1 in case of error. + */ +static int init_for_scan(TABLE* table) { + int error; + if ((error= table->file->ha_rnd_init(TRUE))) { + WSREP_ERROR("Failed to init table for scan: %d", error); + return 1; + } + return 0; +} + +/* + Scan next record. For return codes see handler::ha_rnd_next() + + @return 0 in case of success, error code in case of error + */ +static int next_record(TABLE* table) { + int error; + if ((error= table->file->ha_rnd_next(table->record[0])) && + error != HA_ERR_END_OF_FILE) { + WSREP_ERROR("Failed to read next record: %d", error); + } + return error; +} + +/* + End scan. + + @return 0 in case of success, 1 in case of error. + */ +static int end_scan(TABLE* table) { + int error; + if ((error= table->file->ha_rnd_end())) { + WSREP_ERROR("Failed to end scan: %d", error); + return 1; + } + return 0; +} + +/* + Scan wsrep uuid from given field. + + @return 0 in case of success, 1 in case of error. + */ +static int scan(TABLE* table, uint field, wsrep_uuid_t& uuid) +{ + assert(field < table->s->fields); + int error; + String uuid_str; + (void)table->field[field]->val_str(&uuid_str); + if ((error= wsrep_uuid_scan((const char*)uuid_str.c_ptr(), + uuid_str.length(), + &uuid) < 0)) { + WSREP_ERROR("Failed to scan uuid: %d", -error); + return 1; + } + return 0; +} + +template <typename INTTYPE> +static int scan(TABLE* table, uint field, INTTYPE& val) +{ + assert(field < table->s->fields); + val= table->field[field]->val_int(); + return 0; +} + +static int scan(TABLE* table, uint field, char* strbuf, uint strbuf_len) +{ + String str; + (void)table->field[field]->val_str(&str); + strncpy(strbuf, str.c_ptr(), std::min(str.length(), strbuf_len)); + strbuf[strbuf_len - 1] = '\0'; + return 0; +} + +/* + Scan member + TODO: filter members by cluster UUID + */ +static int scan_member(TABLE* table, + wsrep_uuid_t const cluster_uuid, + std::vector<wsrep_member_info_t>& members) +{ + wsrep_member_info_t member; + + memset(&member, 0, sizeof(member)); + + if (scan(table, 0, member.id) || + scan(table, 2, member.name, sizeof(member.name)) || + scan(table, 3, member.incoming, sizeof(member.incoming))) { + return 1; + } + + if (members.empty() == false) { + assert(memcmp(&members.rbegin()->id, &member.id, sizeof(member.id)) < 0); + } + + try { + members.push_back(member); + } + catch (...) { + WSREP_ERROR("Caught exception while scanning members table"); + return 1; + } + return 0; +} + + +/* + Init table for index scan and retrieve first record + + @return 0 in case of success, error code in case of error. + */ +static int init_for_index_scan(TABLE* table, const uchar* key, + key_part_map map) { + int error; + if ((error= table->file->ha_index_init(table->s->primary_key, true))) { + WSREP_ERROR("Failed to init table for index scan: %d", error); + return error; + } + + error= table->file->ha_index_read_map(table->record[0], + key, map, HA_READ_KEY_EXACT); + switch(error) { + case 0: + case HA_ERR_END_OF_FILE: + case HA_ERR_KEY_NOT_FOUND: + break; + case -1: + WSREP_DEBUG("init_for_index_scan interrupted"); + break; + default: + WSREP_ERROR("init_for_index_scan failed to read first record, error %d", error); + } + return error; +} + +/* + Scan next index record. For return codes see handler::ha_index_next() + + @return 0 in case of success, error code in case of error + */ +/* +static int next_index_record(TABLE* table) { + int error; + if ((error= table->file->ha_index_next(table->record[0])) && + error != HA_ERR_END_OF_FILE) { + WSREP_ERROR("Failed to read next record: %d", error); + } + return error; +} +*/ + +/* + End index scan. + + @return 0 in case of success, 1 in case of error. + */ +static int end_index_scan(TABLE* table) { + int error; + if ((error= table->file->ha_index_end())) { + WSREP_ERROR("Failed to end scan: %d", error); + return 1; + } + return 0; +} + +static void make_key(TABLE* table, uchar* key, key_part_map* map, int parts) { + uint prefix_length= 0; + KEY_PART_INFO* key_part= table->key_info->key_part; + for (int i=0; i < parts; i++) + prefix_length += key_part[i].store_length; + *map = make_prev_keypart_map(parts); + key_copy(key, table->record[0], table->key_info, prefix_length); +} + + +static int apply_frag(THD* thd, TABLE* table, wsrep_uuid_t cluster_uuid) +{ + int ret= 0; + wsrep_trx_meta_t meta; + String buf; + int32_t flags; + + Wsrep_schema_impl::scan(table, 0, meta.stid.node); + Wsrep_schema_impl::scan(table, 1, meta.stid.trx); + Wsrep_schema_impl::scan(table, 2, meta.gtid.seqno); + Wsrep_schema_impl::scan(table, 3, flags); + meta.gtid.uuid= cluster_uuid; + + WSREP_INFO("apply frag %llu %lld", (unsigned long long)meta.stid.trx, (long long)meta.gtid.seqno); + (void)table->field[4]->val_str(&buf); + + wsrep_buf_t const ws = { buf.c_ptr(), buf.length() }; + wsrep_apply_error err; + if ((ret = wsrep_apply(thd, flags, &ws, &meta, err)) + != WSREP_RET_SUCCESS) { + WSREP_WARN("Failed to apply frag: %d, %s", + ret, err.c_str() ? err.c_str() : "(null)"); + } + + thd->store_globals(); /* Restore orig thd context */ + return ret; +} + +} /* namespace Wsrep_schema_impl */ + + +Wsrep_schema::Wsrep_schema(Wsrep_thd_pool* thd_pool) + : + thd_pool_(thd_pool) +{ + assert(thd_pool_); +} + +Wsrep_schema::~Wsrep_schema() +{ } + +int Wsrep_schema::init() +{ + DBUG_ENTER("Wsrep_schema::init()"); + int ret; + THD* thd= thd_pool_->get_thd(0); + if (!thd) { + WSREP_ERROR("Unable to get thd"); + DBUG_RETURN(1); + } + + if (Wsrep_schema_impl::execute_SQL(thd, create_wsrep_schema_str.c_str(), + create_wsrep_schema_str.size()) || + Wsrep_schema_impl::execute_SQL(thd, create_cluster_table_str.c_str(), + create_cluster_table_str.size()) || + Wsrep_schema_impl::execute_SQL(thd, create_members_table_str.c_str(), + create_members_table_str.size()) || +#ifdef WSREP_SCHEMA_MEMBERS_HISTORY + Wsrep_schema_impl::execute_SQL(thd, + create_members_history_table_str.c_str(), + create_members_history_table_str.size()) || +#endif /* WSREP_SCHEMA_MEMBERS_HISTORY */ + Wsrep_schema_impl::execute_SQL(thd, + create_frag_table_str.c_str(), + create_frag_table_str.size())) { + ret= 1; + } + else { + ret= 0; + } + thd_pool_->release_thd(thd); + DBUG_RETURN(ret); +} + +int Wsrep_schema::store_view(const wsrep_view_info_t* view) +{ + DBUG_ENTER("Wsrep_schema::store_view()"); + assert(view->status == WSREP_VIEW_PRIMARY); + int ret= 1; + int error; + + TABLE* cluster_table= 0; + TABLE* members_table= 0; +#ifdef WSREP_SCHEMA_MEMBERS_HISTORY + TABLE* members_history_table= 0; +#endif /* WSREP_SCHEMA_MEMBERS_HISTORY */ + wsrep_gtid_t last_committed= WSREP_GTID_UNDEFINED; + + THD* thd= thd_pool_->get_thd(0); + if (!thd) { + WSREP_ERROR("Could not allocate thd"); + DBUG_RETURN(1); + } + + int wsrep_on= thd->variables.wsrep_on; + int sql_log_bin= thd->variables.sql_log_bin; + ulonglong option_bits= thd->variables.option_bits; + + /* + Disable binlogging. + */ + thd->variables.wsrep_on= 0; + thd->variables.sql_log_bin= 0; + thd->variables.option_bits&= ~OPTION_BIN_LOG; + + if (trans_begin(thd, MYSQL_START_TRANS_OPT_READ_WRITE)) { + WSREP_ERROR("failed to start transaction"); + goto out; + } + + /* + Clean up cluster table and members table. + */ + if (Wsrep_schema_impl::execute_SQL(thd, + delete_from_cluster_table.c_str(), + delete_from_cluster_table.size()) || + Wsrep_schema_impl::execute_SQL(thd, + delete_from_members_table.c_str(), + delete_from_members_table.size())) { + goto out; + } + + /* + Store cluster view info + */ + Wsrep_schema_impl::init_stmt(thd); + if (Wsrep_schema_impl::open_for_write(thd, "cluster", &cluster_table)) { + goto out; + } + + Wsrep_schema_impl::store(cluster_table, 0, view->state_id.uuid); + Wsrep_schema_impl::store(cluster_table, 1, view->view); + Wsrep_schema_impl::store(cluster_table, 2, view->state_id.seqno); + Wsrep_schema_impl::store(cluster_table, 3, view->proto_ver); + if ((error= Wsrep_schema_impl::update_or_insert(cluster_table))) { + WSREP_ERROR("failed to write to cluster table: %d", error); + goto out; + } + Wsrep_schema_impl::finish_stmt(thd); + + /* + Store info about current members + */ + Wsrep_schema_impl::init_stmt(thd); + if (Wsrep_schema_impl::open_for_write(thd, "members", &members_table)) { + WSREP_ERROR("failed to open wsrep.members table"); + goto out; + } + + for (int i= 0; i < view->memb_num; ++i) { + Wsrep_schema_impl::store(members_table, 0, view->members[i].id); + Wsrep_schema_impl::store(members_table, 1, view->state_id.uuid); + Wsrep_schema_impl::store(members_table, 2, + view->members[i].name, + strlen(view->members[i].name)); + Wsrep_schema_impl::store(members_table, 3, + view->members[i].incoming, + strlen(view->members[i].incoming)); + if ((error= Wsrep_schema_impl::update_or_insert(members_table))) { + WSREP_ERROR("failed to write wsrep.members table: %d", error); + goto out; + } + } + Wsrep_schema_impl::finish_stmt(thd); + +#ifdef WSREP_SCHEMA_MEMBERS_HISTORY + /* + Store members history + */ + Wsrep_schema_impl::init_stmt(thd); + if (Wsrep_schema_impl::open_for_write(thd, "members_history", + &members_history_table)) { + WSREP_ERROR("failed to open wsrep.members table"); + goto out; + } + + for (int i= 0; i < view->memb_num; ++i) { + Wsrep_schema_impl::store(members_history_table, 0, view->members[i].id); + Wsrep_schema_impl::store(members_history_table, 1, view->state_id.uuid); + Wsrep_schema_impl::store(members_history_table, 2, view->view); + Wsrep_schema_impl::store(members_history_table, 3, + view->state_id.seqno); + Wsrep_schema_impl::store(members_history_table, 4, + view->members[i].name, + strlen(view->members[i].name)); + Wsrep_schema_impl::store(members_history_table, 5, + view->members[i].incoming, + strlen(view->members[i].incoming)); + if ((error= Wsrep_schema_impl::update_or_insert(members_history_table))) { + WSREP_ERROR("failed to write wsrep.members table: %d", error); + goto out; + } + } + Wsrep_schema_impl::finish_stmt(thd); +#endif /* WSREP_SCHEMA_MEMBERS_HISTORY */ + + /* + Assign wsrep GTID before commit if view state_id contains unique + seqno. + */ + wsrep_last_committed_id(&last_committed); + if (last_committed.seqno < view->state_id.seqno) + { + WSREP_DEBUG("Assigning unique seqno for view %lld", + (long long)view->state_id.seqno); + thd->wsrep_trx_meta.gtid= view->state_id; + if (wsrep_write_dummy_event_low(thd, "view event")) + { + WSREP_ERROR("Dummy event write failed"); + goto out; + } + } + else + { + WSREP_DEBUG("View does not have unique seqno or the view event was " + "contained in SST"); + } + + if (!trans_commit(thd)) { + /* Success */ + ret= 0; + } + + out: + + if (ret) { + WSREP_ERROR("Failed to write view event into wsrep_schema"); + trans_rollback_stmt(thd); + if (!trans_rollback(thd)) { + close_thread_tables(thd); + } + } + thd->mdl_context.release_transactional_locks(); + + /* Restore original thd state */ + thd->variables.wsrep_on= wsrep_on; + thd->variables.sql_log_bin= sql_log_bin; + thd->variables.option_bits= option_bits; + thd->wsrep_trx_meta.gtid= WSREP_GTID_UNDEFINED; + + thd_pool_->release_thd(thd); + + DBUG_RETURN(ret); +} + +int Wsrep_schema::restore_view(const wsrep_uuid_t& node_uuid, + wsrep_view_info_t** view_info) const { + DBUG_ENTER("Wsrep_schema::restore_view()"); + assert(view_info); + int ret= 1; + int error; + THD* thd= thd_pool_->get_thd(0); + + TABLE* cluster_table= 0; + TABLE* members_table=0; + + wsrep_uuid_t cluster_uuid; + wsrep_seqno_t view_id; + wsrep_seqno_t view_seqno; + int my_idx= -1; + int proto_ver; + std::vector<wsrep_member_info_t> members; + + if (!thd) { + WSREP_ERROR("Failed to allocate THD for restore view"); + DBUG_RETURN(1); + } + + if (trans_begin(thd, MYSQL_START_TRANS_OPT_READ_ONLY)) { + WSREP_ERROR("Failed to start transaction"); + goto out; + } + + /* + Read cluster info from cluster table + */ + Wsrep_schema_impl::init_stmt(thd); + if (Wsrep_schema_impl::open_for_read(thd, "cluster", &cluster_table) || + Wsrep_schema_impl::init_for_scan(cluster_table) || + Wsrep_schema_impl::next_record(cluster_table) || + Wsrep_schema_impl::scan(cluster_table, 0, cluster_uuid) || + Wsrep_schema_impl::scan(cluster_table, 1, view_id) || + Wsrep_schema_impl::scan(cluster_table, 2, view_seqno) || + Wsrep_schema_impl::scan(cluster_table, 3, proto_ver) || + Wsrep_schema_impl::end_scan(cluster_table)) { + goto out; + } + Wsrep_schema_impl::finish_stmt(thd); + + /* + Read members from members table + */ + Wsrep_schema_impl::init_stmt(thd); + if (Wsrep_schema_impl::open_for_read(thd, "members", &members_table) || + Wsrep_schema_impl::init_for_scan(members_table)) { + goto out; + } + + while (true) { + if ((error= Wsrep_schema_impl::next_record(members_table)) == 0) { + if (Wsrep_schema_impl::scan_member(members_table, + cluster_uuid, + members)) { + goto out; + } + } + else if (error == HA_ERR_END_OF_FILE) { + break; + } + else { + goto out; + } + } + + if (Wsrep_schema_impl::end_scan(members_table)) { + goto out; + } + Wsrep_schema_impl::finish_stmt(thd); + + for (uint i= 0; i < members.size(); ++i) { + if (memcmp(&members[i].id, &node_uuid, sizeof(node_uuid)) == 0) { + my_idx= i; + } + } + + *view_info= (wsrep_view_info_t*) + malloc(sizeof(wsrep_view_info_t) + + members.size() * sizeof(wsrep_member_info_t)); + if (!view_info) { + WSREP_ERROR("Failed to allocate memory for view info"); + goto out; + } + + (*view_info)->state_id.uuid= cluster_uuid; + (*view_info)->state_id.seqno= view_seqno; + (*view_info)->view= view_id; + (*view_info)->status= WSREP_VIEW_PRIMARY; + (*view_info)->my_idx= my_idx; + (*view_info)->proto_ver= proto_ver; + (*view_info)->memb_num= members.size(); + std::copy(members.begin(), members.end(), (*view_info)->members); + + (void)trans_commit(thd); + ret= 0; /* Success*/ + out: + + if (ret) { + trans_rollback_stmt(thd); + if (!trans_rollback(thd)) { + close_thread_tables(thd); + } + } + thd->mdl_context.release_transactional_locks(); + + thd_pool_->release_thd(thd); + DBUG_RETURN(ret); +} + +int Wsrep_schema::append_frag_apply(THD* thd, + const wsrep_trx_meta_t& meta, + const uint32_t flags, + const unsigned char* frag, + size_t frag_len) +{ + DBUG_ENTER("Wsrep_schema::append_frag_apply"); + int error, ret= 1; + TABLE* frag_table= 0; + int wsrep_on= thd->variables.wsrep_on; + int sql_log_bin= thd->variables.sql_log_bin; + ulonglong log_bin_option= (thd->variables.option_bits & OPTION_BIN_LOG); + my_bool skip_locking= thd->wsrep_skip_locking; + + thd->variables.wsrep_on= 0; + thd->variables.sql_log_bin= 0; + thd->variables.option_bits&= ~OPTION_BIN_LOG; + thd->wsrep_skip_locking= TRUE; + + assert(meta.stid.trx != WSREP_UNDEFINED_TRX_ID); + assert(wsrep_uuid_compare(&meta.stid.node, &WSREP_UUID_UNDEFINED) != 0); + + if (trans_begin(thd, MYSQL_START_TRANS_OPT_READ_WRITE)) { + WSREP_ERROR("Failed to start transaction"); + goto out; + } + + Wsrep_schema_impl::init_stmt(thd); + if (Wsrep_schema_impl::open_for_write(thd, "SR", &frag_table)) { + goto out; + } + + Wsrep_schema_impl::store(frag_table, 0, meta.stid.node); + Wsrep_schema_impl::store(frag_table, 1, meta.stid.trx); + Wsrep_schema_impl::store(frag_table, 2, meta.gtid.seqno); + Wsrep_schema_impl::store(frag_table, 3, flags); + Wsrep_schema_impl::store(frag_table, 4, frag, frag_len); + + /* TODO: make this insert only */ + if ((error= Wsrep_schema_impl::insert(frag_table))) { + WSREP_ERROR("Failed to write to frag table: %d", error); + goto out; + } + Wsrep_schema_impl::finish_stmt(thd); + + if (!(flags & (WSREP_FLAG_TRX_END | WSREP_FLAG_ROLLBACK)) && + meta.gtid.seqno != WSREP_SEQNO_UNDEFINED) + { + thd->wsrep_trx_meta= meta; + if (wsrep_write_dummy_event_low(thd, "fragment")) + { + goto out; + } + } + ret= 0; + +out: + thd->variables.wsrep_on= wsrep_on; + thd->variables.sql_log_bin= sql_log_bin; + thd->variables.option_bits|= log_bin_option; + thd->wsrep_skip_locking= skip_locking; + DBUG_RETURN(ret); +} + +THD* Wsrep_schema::append_frag(const wsrep_trx_meta_t& meta, + const uint32_t flags, + const unsigned char* frag, + size_t frag_len) +{ + DBUG_ENTER("Wsrep_schema::append_frag"); + + THD* thd= thd_pool_->get_thd(0); + + if (!thd) { + WSREP_ERROR("Could not allocate thd"); + goto out; + } + + if (append_frag_apply(thd, meta, flags, frag, frag_len)) { + goto out; + } + + DBUG_RETURN(thd); + +out: + if (thd) release_SR_thd(thd); + DBUG_RETURN(NULL); +} + +int Wsrep_schema::append_frag_commit(const wsrep_trx_meta_t& meta, + const uint32_t flags, + const unsigned char* frag, + size_t frag_len) +{ + DBUG_ENTER("Wsrep_schema::append_frag_commit"); + + THD* thd; + int ret= 1; + enum durability_properties dur_save; + + + if ((thd= append_frag(meta, flags, frag, frag_len)) == NULL) + goto out; + + /* + We can ignore the storage engine durability setting here: + Committing a fragment does not cause actual transaction to + be committed, so it will be enough that the fragment is + committed in order to be able to recover to consistent state. + */ + dur_save= thd->durability_property; + thd->durability_property= HA_IGNORE_DURABILITY; + + if (!trans_commit(thd)) { + /* Success */ + ret= 0; + } + + thd->durability_property= dur_save; + +out: + if (thd) { + thd->mdl_context.release_transactional_locks(); + thd_pool_->release_thd(thd); + } + DBUG_RETURN(ret); +} + +int Wsrep_schema::update_frag_seqno(THD* thd, const wsrep_trx_meta_t& meta) +{ + DBUG_ENTER("Wsrep_schema::update_frag_seqno"); + WSREP_DEBUG("update_frag_seqno(%lld) trx %ld, seqno %lld", + thd->thread_id, meta.stid.trx, (long long)meta.gtid.seqno); + int error, ret= 1; + uchar key[MAX_KEY_LENGTH]; + key_part_map key_map= 0; + TABLE* frag_table= 0; + my_bool skip_locking= thd->wsrep_skip_locking; + thd->wsrep_skip_locking= TRUE; + + assert(meta.gtid.seqno != WSREP_SEQNO_UNDEFINED); + + Wsrep_schema_impl::init_stmt(thd); + if (Wsrep_schema_impl::open_for_write(thd, "SR", &frag_table)) { + goto out; + } + + /* Find record with the given uuid, trx id, and seqno -1 */ + Wsrep_schema_impl::store(frag_table, 0, meta.stid.node); + Wsrep_schema_impl::store(frag_table, 1, meta.stid.trx); + Wsrep_schema_impl::store(frag_table, 2, -1); + Wsrep_schema_impl::make_key(frag_table, key, &key_map, 3); + + if ((error= Wsrep_schema_impl::init_for_index_scan(frag_table, key, key_map))) { + if (error == HA_ERR_END_OF_FILE || error == HA_ERR_KEY_NOT_FOUND) { + WSREP_ERROR("Record not found in %s.%s: %d", + frag_table->s->db.str, + frag_table->s->table_name.str, + error); + } + frag_table->file->print_error(error, MYF(0)); + goto out; + } + + /* Copy the original record to frag_table->record[1] */ + store_record(frag_table, record[1]); + + /* Store seqno in frag_table->record[0] and update the row */ + Wsrep_schema_impl::store(frag_table, 2, meta.gtid.seqno); + if ((error= frag_table->file->ha_update_row(frag_table->record[1], + frag_table->record[0]))) { + WSREP_ERROR("Error updating record in %s.%s: %d", + frag_table->s->db.str, + frag_table->s->table_name.str, + error); + frag_table->file->print_error(error, MYF(0)); + ret= error; + goto out; + } + + if (Wsrep_schema_impl::end_index_scan(frag_table)) { + goto out; + } + + Wsrep_schema_impl::finish_stmt(thd); + + thd->wsrep_trx_meta= meta; + if (wsrep_write_dummy_event_low(thd, "fragment")) + { + goto out; + } + + if (!trans_commit(thd)) { + /* Success */ + ret= 0; + } + +out: + thd->wsrep_skip_locking= skip_locking; + if (ret) { + trans_rollback_stmt(thd); + if (!trans_rollback(thd)) { + close_thread_tables(thd); + } + } + thd->mdl_context.release_transactional_locks(); + thd_pool_->release_thd(thd); + DBUG_RETURN(ret); +} + +void Wsrep_schema::release_SR_thd(THD* thd) +{ + trans_rollback_stmt(thd); + if (!trans_rollback(thd)) { + close_thread_tables(thd); + } + thd->mdl_context.release_transactional_locks(); + thd_pool_->release_thd(thd); +} + +static int remove_fragment(THD* thd, TABLE* frag_table, + const wsrep_trx_meta& meta) +{ + WSREP_DEBUG("remove_fragment(%lld) trx %ld, seqno %lld", + thd->thread_id, meta.stid.trx, (long long)meta.gtid.seqno); + int error, ret= 1; + uchar key[MAX_KEY_LENGTH]; + key_part_map key_map= 0; + + assert(meta.stid.trx != WSREP_UNDEFINED_TRX_ID); + assert(wsrep_uuid_compare(&meta.stid.node, &WSREP_UUID_UNDEFINED) != 0); + + /* + Remove record with the given uuid, trx id, and seqno. + Using a complete key here avoids gap locks. + */ + Wsrep_schema_impl::store(frag_table, 0, meta.stid.node); + Wsrep_schema_impl::store(frag_table, 1, meta.stid.trx); + Wsrep_schema_impl::store(frag_table, 2, meta.gtid.seqno); + Wsrep_schema_impl::make_key(frag_table, key, &key_map, 3); + + if ((error= Wsrep_schema_impl::init_for_index_scan(frag_table, key, key_map))) { + if (error == HA_ERR_END_OF_FILE || error == HA_ERR_KEY_NOT_FOUND) { + WSREP_WARN("Record not found in %s.%s:trx %ld, seqno %lld, error %d", + frag_table->s->db.str, + frag_table->s->table_name.str, + meta.stid.trx, + (long long)meta.gtid.seqno, + error); + } + frag_table->file->print_error(error, MYF(0)); + ret= error; + goto out; + } + + if (Wsrep_schema_impl::delete_row(frag_table)) { + goto out; + } + + ret= 0; + + out: + Wsrep_schema_impl::end_index_scan(frag_table); + return ret; +} + +int Wsrep_schema::remove_trx(THD* thd, wsrep_fragment_set* fragments) +{ + DBUG_ENTER("Wsrep_schema::remove_trx()"); + WSREP_DEBUG("Wsrep_schema::remove_trx(%lld)", thd->thread_id); + int wsrep_on= thd->variables.wsrep_on; + int sql_log_bin= thd->variables.sql_log_bin; + ulonglong log_bin_option= (thd->variables.option_bits & OPTION_BIN_LOG); + my_bool skip_locking= thd->wsrep_skip_locking; + + thd->variables.wsrep_on= 0; + thd->variables.sql_log_bin= 0; + thd->variables.option_bits&= ~OPTION_BIN_LOG; + thd->wsrep_skip_locking= TRUE; + + TABLE* frag_table= 0; + bool was_opened= false; + if (thd->open_tables) { + for (TABLE* t= thd->open_tables; t != NULL; t= t->next) { + if (!strcmp(t->s->db.str, "wsrep_schema") && + !strcmp(t->s->table_name.str, "SR")) { + frag_table= t; + empty_record(frag_table); + frag_table->use_all_columns(); + restore_record(frag_table, s->default_values); + break; + } + } + } + else { + (void)Wsrep_schema_impl::open_for_write(thd, "SR", &frag_table); + was_opened= true; + } + DBUG_ASSERT(frag_table); + + int ret= 1; + if (frag_table) { + wsrep_fragment_set::const_iterator it= fragments->begin(); + for (; it!= fragments->end(); it++) { + if (int error= remove_fragment(thd, frag_table, *it)) { + ret= error; + break; + } + } + if (it == fragments->end()) { + ret= 0; + } + } + else { + WSREP_WARN("SR table not open in remove_trx()"); + } + + if (was_opened) { + trans_commit_stmt(thd); + close_thread_tables(thd); + } + + thd->variables.wsrep_on= wsrep_on; + thd->variables.sql_log_bin= sql_log_bin; + thd->variables.option_bits|= log_bin_option; + thd->wsrep_skip_locking= skip_locking; + + DBUG_RETURN(ret); +} + +int Wsrep_schema::rollback_trx(THD* caller) +{ + DBUG_ENTER("Wsrep_schema::rollback_trx"); + WSREP_DEBUG("Wsrep_schema::rollback_trx(%lld)", caller->thread_id); + + /* + There are cases where rollback_trx is called unnecessarily from + wsrep_client_rollback(). + For instance, after_command() -> wsrep_client_rollback() -> rollback_trx() + is not necessary. + However, wsrep_client_rollback() is also called when a server transitions + from non-primary back to primary, in which case we want to clean up the + SR table. We should fix this eventually, and replace the following if + statement with assert. + */ + if (caller->wsrep_SR_fragments.empty()) { + WSREP_DEBUG("Wsrep_schema::rollback_trx(%lld) no fragments to remove", + caller->thread_id); + DBUG_RETURN(0); + } + + THD* thd= thd_pool_->get_thd(0); + + if (!thd) { + WSREP_ERROR("Could not allocate thd"); + DBUG_RETURN(1); + } + + if (trans_begin(thd, MYSQL_START_TRANS_OPT_READ_WRITE)) { + WSREP_ERROR("Failed to start transaction"); + DBUG_RETURN(1); + } + + Wsrep_schema_impl::init_stmt(thd); + int ret= remove_trx(thd, &caller->wsrep_SR_fragments); + Wsrep_schema_impl::finish_stmt(thd); + + if (!ret && !trans_commit(thd)) { + /* Success */ + ret= 0; + } + + if (ret) { + trans_rollback_stmt(thd); + if (!trans_rollback(thd)) { + close_thread_tables(thd); + } + } + thd->mdl_context.release_transactional_locks(); + + thd_pool_->release_thd(thd); + + DBUG_RETURN(ret); +} + +int Wsrep_schema::restore_frags() +{ + DBUG_ENTER("Wsrep_schema::restore_frags()"); + int ret= 1; + int error; + wsrep_uuid_t cluster_uuid; + TABLE* frag_table= 0; + TABLE* cluster_table= 0; + + + THD* thd= thd_pool_->get_thd(0); + + WSREP_INFO("Restoring SR fragments from table storage"); + + if (!thd) { + WSREP_ERROR("Failed to allocate THD for restore view"); + DBUG_RETURN(1); + } + + + if (trans_begin(thd, MYSQL_START_TRANS_OPT_READ_ONLY)) { + WSREP_ERROR("Failed to start transaction"); + goto out; + } + + /* + Scan cluster uuid first + */ + Wsrep_schema_impl::init_stmt(thd); + if (Wsrep_schema_impl::open_for_read(thd, "cluster", &cluster_table) || + Wsrep_schema_impl::init_for_scan(cluster_table)) { + goto out; + } + if ((error= Wsrep_schema_impl::next_record(cluster_table)) == 0) { + if (Wsrep_schema_impl::scan(cluster_table, 0, cluster_uuid)) { + goto out; + } + } + else if (error == HA_ERR_END_OF_FILE) { + WSREP_ERROR("Cluster table is empty!"); + goto out; + } + else { + WSREP_ERROR("Cluster table scan returned error: %d", errno); + goto out; + } + if (Wsrep_schema_impl::end_scan(cluster_table)) { + goto out; + } + Wsrep_schema_impl::finish_stmt(thd); + + /* + Scan all fragments and apply them + */ + Wsrep_schema_impl::init_stmt(thd); + if (Wsrep_schema_impl::open_for_read(thd, "SR", &frag_table) || + Wsrep_schema_impl::init_for_scan(frag_table)) { + goto out; + } + while (true) { + if ((error= Wsrep_schema_impl::next_record(frag_table)) == 0) { + if (Wsrep_schema_impl::apply_frag(thd, frag_table, cluster_uuid)) { + goto out; + } + } + else if (error == HA_ERR_END_OF_FILE) { + break; + } + else { + WSREP_ERROR("Frag table scan returned error: %d", error); + goto out; + } + } + if (Wsrep_schema_impl::end_scan(frag_table)) { + goto out; + } + Wsrep_schema_impl::finish_stmt(thd); + + (void)trans_commit(thd); + ret= 0; /* Success*/ + + WSREP_INFO("SR fragments restored"); + out: + + if (ret) { + trans_rollback_stmt(thd); + if (!trans_rollback(thd)) { + close_thread_tables(thd); + } + } + thd->mdl_context.release_transactional_locks(); + + thd_pool_->release_thd(thd); + DBUG_RETURN(ret); + +} + + +int Wsrep_schema::replay_trx(THD* real_thd, const wsrep_trx_meta_t& meta) +{ + int ret= 1; + int error; + TABLE* frag_table= 0; + uchar key[MAX_KEY_LENGTH]; + key_part_map key_map= 0; + + THD* thd= thd_pool_->get_thd(0); + wsrep_fragment_set* fragments= &real_thd->wsrep_SR_fragments; + wsrep_fragment_set::const_iterator it= fragments->begin(); + + assert(!fragments->empty()); + + if (trans_begin(thd, MYSQL_START_TRANS_OPT_READ_ONLY)) { + WSREP_ERROR("Failed to start transaction"); + goto out; + } + + Wsrep_schema_impl::init_stmt(thd); + if (Wsrep_schema_impl::open_for_read(thd, "SR", &frag_table)) { + goto out; + } + + for (; it!= fragments->end(); it++) { + Wsrep_schema_impl::store(frag_table, 0, meta.stid.node); + Wsrep_schema_impl::store(frag_table, 1, meta.stid.trx); + Wsrep_schema_impl::store(frag_table, 2, (*it).gtid.seqno); + Wsrep_schema_impl::make_key(frag_table, key, &key_map, 3); + + error= Wsrep_schema_impl::init_for_index_scan(frag_table, key, key_map); + if (error == HA_ERR_END_OF_FILE || error == HA_ERR_KEY_NOT_FOUND) { + break; + } else if (error > 0) { + WSREP_ERROR("Frag table scan returned error: %d", error); + ret= error; + goto out; + } + + wsrep_trx_meta_t meta; + int32_t flags; + Wsrep_schema_impl::scan(frag_table, 0, meta.stid.node); + Wsrep_schema_impl::scan(frag_table, 1, meta.stid.trx); + Wsrep_schema_impl::scan(frag_table, 2, meta.gtid.seqno); + Wsrep_schema_impl::scan(frag_table, 3, flags); + + WSREP_INFO("replay frag trx_id: %llu seqno: %lld flags: %x", + (unsigned long long)meta.stid.trx, + (long long)meta.gtid.seqno, flags); + + String buf; + (void)frag_table->field[4]->val_str(&buf); + /* + Call wsrep_apply_events() directly to bypass SR processing in + wsrep_apply_cb(). + */ + real_thd->store_globals(); + error= wsrep_apply_events(real_thd, buf.c_ptr_safe(), buf.length()); + if (error != WSREP_CB_SUCCESS) { + ret= error; + WSREP_ERROR("Failed to apply events during replay, error: %d", error); + goto out; + } + thd->store_globals(); + if (Wsrep_schema_impl::end_index_scan(frag_table)) { + goto out; + } + } + Wsrep_schema_impl::finish_stmt(thd); + + thd->store_globals(); + (void)trans_commit(thd); + real_thd->store_globals(); + remove_trx(real_thd, &real_thd->wsrep_SR_fragments); + (void)trans_commit(real_thd); + ret= 0; /* Success*/ + + WSREP_INFO("SR transaction replayed"); + out: + + if (ret) { + trans_rollback_stmt(thd); + if (!trans_rollback(thd)) { + close_thread_tables(thd); + } + } + thd->mdl_context.release_transactional_locks(); + + thd_pool_->release_thd(thd); + + real_thd->store_globals(); + real_thd->mdl_context.release_transactional_locks(); + + return ret; +} + +void Wsrep_schema::init_SR_table(TABLE_LIST *table) +{ +#ifdef OUT + table->init_one_table(wsrep_schema_str.c_str(), + wsrep_schema_str.size(), + "SR", 2, "SR", TL_WRITE); +#endif + //LEX_CSTRING schema_str= { C_STRING_WITH_LEN(wsrep_schema_str.c_str()) }; + LEX_CSTRING schema_str= { wsrep_schema_str.c_str(), wsrep_schema_str.length() }; + LEX_CSTRING table_str= { "SR", 2 }; + table->init_one_table(&schema_str, &table_str, NULL, TL_WRITE); +} diff --git a/sql/wsrep_schema.h b/sql/wsrep_schema.h new file mode 100644 index 00000000000..f8ab70d0cd1 --- /dev/null +++ b/sql/wsrep_schema.h @@ -0,0 +1,141 @@ +/* Copyright (C) 2015-2017 Codership Oy <info@codership.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + + +#ifndef WSREP_SCHEMA_H +#define WSREP_SCHEMA_H + +#include "mysqld.h" +#include "thr_lock.h" /* enum thr_lock_type */ +#include "../wsrep/wsrep_api.h" +#include "wsrep_mysqld.h" + +#include <string> + +/* + Forward decls +*/ +class THD; +struct TABLE; +struct TABLE_LIST; +struct st_mysql_lex_string; +typedef struct st_mysql_lex_string LEX_STRING; + +class Wsrep_thd_pool; + +/** Name of the system database (schema) used for WSREP related data. */ +extern const std::string wsrep_schema_str; + +/** Name of the table in `wsrep_schema_str` used for storing streaming +replication data. In an InnoDB full format, e.g. "database/tablename". */ +extern const std::string sr_table_name_full_str; + +class Wsrep_schema +{ + public: + + Wsrep_schema(Wsrep_thd_pool*); + ~Wsrep_schema(); + + /* + Initialize wsrep schema. Storage engines must be running before + calling this function. + */ + int init(); + + /* + Store wsrep view info into wsrep schema. + */ + int store_view(const wsrep_view_info_t*); + + /* + Restore view info from stable storage. + */ + int restore_view(const wsrep_uuid_t& node_uuid, wsrep_view_info_t**) const; + + /* + Append transaction fragment to fragment storage. + Starts a trx using a THD from thd_pool, does not commit. + Should be followed by a call to update_frag_seqno(), or + release_SR_thd() if wsrep->certify() fails. + */ + THD* append_frag(const wsrep_trx_meta_t&, uint32_t, + const unsigned char*, size_t); + + /* + Update fragment sequence number and commits. + Use in combination with append_frag(). + */ + int update_frag_seqno(THD* thd, const wsrep_trx_meta_t&); + + /* + Rollback and release thd returned from append_frag(). + */ + void release_SR_thd(THD* thd); + + /* + Append transaction fragment to fragment storage. + Starts a trx using the given THD, does not commit. + */ + int append_frag_apply(THD* thd, const wsrep_trx_meta_t&, + uint32_t, const unsigned char*, size_t); + + /* + Append transaction fragment to fragment storage. + Starts a trx using a THD from thd_pool and commits. + */ + int append_frag_commit(const wsrep_trx_meta_t&, uint32_t, + const unsigned char*, size_t); + + /* + Remove transaction from fragment storage in thd's transaction context + */ + int remove_trx(THD* thd, wsrep_fragment_set* fragments); + + /* + Remove transaction from fragment storage + */ + int rollback_trx(THD* thd); + + /* + Restore and apply all transaction fragments from fragment storage + */ + int restore_frags(); + + /* + Replay a transaction from fragments stored in wsrep schema + */ + int replay_trx(THD*, const wsrep_trx_meta_t&); + + /* + Init TABLE_LIST entry for SR table + */ + void init_SR_table(TABLE_LIST *table); + + /* + Close wsrep schema. + */ + void close(); + + private: + /* Non-copyable */ + Wsrep_schema(const Wsrep_schema&); + Wsrep_schema& operator=(const Wsrep_schema&); + + Wsrep_thd_pool* thd_pool_; +}; + + +#endif /* !WSREP_SCHEMA_H */ diff --git a/sql/wsrep_sr.cc b/sql/wsrep_sr.cc new file mode 100644 index 00000000000..c007aacb991 --- /dev/null +++ b/sql/wsrep_sr.cc @@ -0,0 +1,428 @@ +/* Copyright (C) 2013-2016 Codership Oy <info@codership.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + +#include <my_global.h> +#include "wsrep_applier.h" + +#include "wsrep_priv.h" +#include "wsrep_sr.h" +#include "wsrep_thd.h" +#include "wsrep_trans_observer.h" + +#include "transaction.h" // trans_rollback() +#include "debug_sync.h" // DEBUG_SYNC() + +void wsrep_SR_trx_info::remove(THD* caller, bool persistent) +{ + WSREP_DEBUG("wsrep_SR_trx_info::remove for thd: %lld trx: %lu", + (thd_) ? thd_->thread_id : -1, + (thd_) ? thd_->wsrep_trx_id() : -1); + + if (thd_) { + if (caller) thd_->thread_stack = caller->thread_stack; + thd_->store_globals(); + /* rollback */ + wsrep_cb_status_t const rcode(trans_rollback_stmt(thd_) || + trans_rollback(thd_) ? + WSREP_CB_FAILURE : WSREP_CB_SUCCESS); + + if (rcode != WSREP_CB_SUCCESS) + WSREP_INFO("SR rollback failed, ret: %d, thd: %lld", rcode,thd_->thread_id); + + /* remove persistency records */ + if (wsrep_SR_store && persistent) wsrep_SR_store->rollback_trx(this); + + /* end and delete thd_ */ + wsrep_end_SR_THD(thd_); + + /* retain working THD */ + if (caller) caller->store_globals(); + thd_ = NULL; + } +} + +void wsrep_SR_trx_info::cleanup() +{ + if (wsrep_SR_store) wsrep_SR_store->remove_trx(this); + get_THD()->store_globals(); +} + +/* to prepare wsrep_uuid_t usable in std::map */ +inline bool operator==(const wsrep_uuid_t& lhs, const wsrep_uuid_t& rhs) { + return(memcmp(lhs.data, rhs.data, 16) == 0); +} +inline bool operator!=(const wsrep_uuid_t& lhs, const wsrep_uuid_t& rhs) { + return !operator==(lhs,rhs); +} +inline bool operator< (const wsrep_uuid_t& lhs, const wsrep_uuid_t& rhs) { + return(memcmp(lhs.data, rhs.data, 16) < 0); +} +inline bool operator> (const wsrep_uuid_t& lhs, const wsrep_uuid_t& rhs) { + return operator< (rhs,lhs); +} +inline bool operator<=(const wsrep_uuid_t& lhs, const wsrep_uuid_t& rhs) { + return !operator> (lhs,rhs); +} +inline bool operator>=(const wsrep_uuid_t& lhs, const wsrep_uuid_t& rhs) { + return !operator< (lhs,rhs); +} + +wsrep_SR_trx_info* SR_pool::find(const wsrep_uuid_t& nodeID, + const uint64_t& trxID) const +{ + wsrep_SR_trx_info* ret(NULL); + wsp::auto_lock lock(&LOCK_wsrep_SR_pool); + + src_pool_t::const_iterator const si(pool_.find(nodeID)); + if (si != pool_.end()) + { + trx_pool_t::const_iterator const ti(si->second.find(trxID)); + if (ti != si->second.end()) + { + wsrep_SR_trx_info* trx = ti->second; + if (!trx->preempted()) + { + ret = trx; + trx->acquire(); + } + } + } + + return ret; +} + +wsrep_SR_trx_info* SR_pool::add(const wsrep_uuid_t& nodeID, + const uint64_t& trxID, + THD *thd) +{ + wsrep_SR_trx_info *trx = new wsrep_SR_trx_info(thd); + + wsp::auto_lock lock(&LOCK_wsrep_SR_pool); + assert(NULL == pool_[nodeID][trxID]); + pool_[nodeID][trxID] = trx; + trx->acquire(); + + return trx; +} + +void SR_pool::remove(THD* caller, const wsrep_uuid_t& nodeID, + const uint64_t& trxID, bool persistent) +{ + WSREP_DEBUG("SR_pool::remove, trx: %lu, persistent: %d", trxID, persistent); + + wsrep_SR_trx_info *trx(NULL); + + { + wsp::auto_lock lock(&LOCK_wsrep_SR_pool); + + src_pool_t::iterator const si(pool_.find(nodeID)); + if (si != pool_.end()) + { + trx_pool_t& trx_pool(si->second); + trx_pool_t::iterator ti(trx_pool.find(trxID)); + if (ti != trx_pool.end()) + { + if (!ti->second->preempted()) + { + trx = ti->second; + trx_pool.erase(ti); + } + } + + if (trx_pool.empty()) pool_.erase(si); + } + } + + if (trx) + { + WSREP_DEBUG("trx->remove for trx: %lu", trxID); + trx->remove(caller, persistent); + delete trx; + } +} + +void SR_pool::removeAll(THD* caller, bool persistent) +{ + WSREP_DEBUG("SR_pool::removeAll, persistent: %d", persistent); + + wsp::auto_lock lock(&LOCK_wsrep_SR_pool); + + src_pool_t::iterator si; + for (si = pool_.begin(); si != pool_.end();) + { + trx_pool_t& trx_pool(si->second); + trx_pool_t::iterator ti(trx_pool.begin()); + + while (ti != trx_pool.end()) + { + wsrep_SR_trx_info *trx = ti->second; + trx->remove(caller, persistent); + delete trx; + ++ti; + } + + pool_.erase(si++); + } +} + +void SR_pool::trimToNodes(THD* caller, + const wsrep_member_info_t nodes[], + int nodeCount) +{ + WSREP_DEBUG("SR_pool::trimToNodes"); + + wsp::auto_lock lock(&LOCK_wsrep_SR_pool); + + src_pool_t::iterator si = pool_.begin(); + while (si != pool_.end()) + { + bool do_remove(true); + for (int i = 0; i< nodeCount; i++) + { + if (si->first == nodes[i].id) + { + do_remove = false; + break; + } + } + + if (do_remove) + { + WSREP_DEBUG("SR_pool::trimToNodes do_remove"); + + /* trx_pool erase will not desctruct individual wsrep_SR_trx_info + objects, must remove them manually here + */ + trx_pool_t& trx_pool(si->second); + trx_pool_t::iterator ti(trx_pool.begin()); + + while (ti != trx_pool.end()) + { + wsrep_SR_trx_info *trx = ti->second; + + WSREP_DEBUG("SR transaction to remove: %lld", trx->get_THD()->thread_id); + + trx->remove(caller, true); + delete trx; + ++ti; + } + + /* now removing full trx_pool map */ + pool_.erase(si++); + } + else + { + ++si; + } + } +} + +bool SR_pool::preempt(THD* thd) +{ + wsp::auto_lock lock(&LOCK_wsrep_SR_pool); + + src_pool_t::iterator si; + for (si = pool_.begin(); si != pool_.end(); ++si) + { + trx_pool_t& trx_pool(si->second); + trx_pool_t::iterator ti(trx_pool.begin()); + while (ti != trx_pool.end()) + { + wsrep_SR_trx_info *trx = ti->second; + if (trx->get_THD() == thd) + { + trx->mark_preempted(); + return true; + } + ++ti; + } + } + + return false; +} + +bool SR_pool::wait_release_and_remove(THD* caller, THD *victim) +{ + wsrep_SR_trx_info *trx(NULL); + + { + wsp::auto_lock lock(&LOCK_wsrep_SR_pool); + + src_pool_t::iterator si; + for (si = pool_.begin(); si != pool_.end();) + { + trx_pool_t& trx_pool(si->second); + + for (trx_pool_t::iterator ti = trx_pool.begin(); + ti != trx_pool.end(); + ++ti) + { + if (ti->second->get_THD() == victim) + { + trx = ti->second; + trx_pool.erase(ti); + break; + } + } + + if (trx_pool.empty()) + { + pool_.erase(si++); + } + else + { + ++si; + } + + } + } + + DBUG_ASSERT(trx); + DBUG_ASSERT(trx->preempted()); + + if (trx) + { + trx->wait_release(); + trx->remove(caller, true); + delete trx; + return true; + } + + return false; +} + + +SR_pool *sr_pool; + +void wsrep_close_SR_transactions(THD *thd) +{ + + if (sr_pool) + { + WSREP_DEBUG("deleting streaming replication transaction pool"); + sr_pool->removeAll(thd, false); + } + else + { + WSREP_DEBUG("empty streaming replication transaction pool"); + } + + if (wsrep_SR_store) wsrep_SR_store->close(); + + delete sr_pool; + sr_pool = NULL; +} + +void trim_SR_pool(THD* thd, const wsrep_member_info_t nodes[], int nodeCount) +{ + sr_pool->trimToNodes(thd, nodes, nodeCount); +} + +void wsrep_init_SR_pool() +{ + WSREP_DEBUG("wsrep_init_SR_pool"); + + /* for time being initialize SR pool here */ + if (!sr_pool) sr_pool = new SR_pool(); +} + +void wsrep_restore_SR_trxs(THD *thd) +{ + if (wsrep_SR_store) wsrep_SR_store->restore(thd); +} + +bool wsrep_preempt_SR_THD(THD *victim_thd) +{ + return sr_pool->preempt(victim_thd); +} + +bool wsrep_abort_SR_THD(THD *thd, THD *victim_thd) +{ + return sr_pool->wait_release_and_remove(thd, victim_thd); +} + +void wsrep_prepare_SR_trx_info_for_rollback(THD *thd) +{ + mysql_mutex_assert_owner(&thd->LOCK_wsrep_thd); + wsrep_uuid_t node_uuid; + wsrep_node_uuid(node_uuid); + + DBUG_ASSERT(thd->wsrep_ws_handle.trx_id != WSREP_UNDEFINED_TRX_ID); + + int error= 1; + THD *sr_thd= wsrep_start_SR_THD(thd->thread_stack); + if (sr_thd) + { + wsrep_SR_trx_info *SR_trx= sr_pool->add(node_uuid, + thd->wsrep_ws_handle.trx_id, + sr_thd); + if (SR_trx) + { + for (wsrep_fragment_set::const_iterator i= + thd->wsrep_SR_fragments.begin(); + i != thd->wsrep_SR_fragments.end(); ++i) + { + SR_trx->append_fragment(&(*i)); + } + SR_trx->release(); + error= 0; + } + } + if (error) + { + WSREP_WARN("Could not create SR trx info for rollback, wsrep_schema.SR " + "table may not be cleaned up for transaction %lu", + thd->wsrep_ws_handle.trx_id); + } + else + { + thd->wsrep_SR_fragments.clear(); + } +} + + +void wsrep_remove_SR_fragments(THD *thd) +{ + if (wsrep_SR_store) wsrep_SR_store->remove_trx(thd); +} + +void wsrep_rollback_SR_trx(THD *thd) +{ + if (wsrep_SR_store) wsrep_SR_store->rollback_trx(thd); + thd->wsrep_SR_fragments.clear(); +} + +void wsrep_prepare_SR_for_open_tables(THD *thd, TABLE_LIST **table_list) +{ + if (wsrep_SR_store) + { + wsrep_SR_store->prepare_for_open_tables(thd, table_list); + } +} + +void wsrep_handle_SR_rollback(void *BF_thd_ptr, void *victim_thd_ptr) +{ + DBUG_ASSERT(victim_thd_ptr); + if (!victim_thd_ptr) return; + + THD *victim_thd = (THD*) victim_thd_ptr; + WSREP_DEBUG("handle SR rollback, for deadlock: thd %lld trx_id %lu frags %lu conf %d", + victim_thd->thread_id, + victim_thd->wsrep_trx_id(), + victim_thd->wsrep_fragments_sent, + victim_thd->wsrep_conflict_state_unsafe()); + (void)wsrep_before_rollback(victim_thd, true); + if (BF_thd_ptr) ((THD*) BF_thd_ptr)->store_globals(); +} diff --git a/sql/wsrep_sr.h b/sql/wsrep_sr.h new file mode 100644 index 00000000000..4b2009ef12d --- /dev/null +++ b/sql/wsrep_sr.h @@ -0,0 +1,275 @@ +/* Copyright 2013-2016 Codership Oy <http://www.codership.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef WSREP_SR_H +#define WSREP_SR_H + +#include "wsrep_mysqld.h" +#include <sys/types.h> +#include <map> +#include "sql_class.h" +#include "wsrep_utils.h" // wsp::auto_lock + +extern class SR_storage_file *wsrep_SR_store_file; +extern class SR_storage_table *wsrep_SR_store_table; +extern class SR_storage *wsrep_SR_store; + +class wsrep_SR_trx_info +{ +private: + THD *thd_; /* THD processing SR transaction */ + my_thread_id applier_thread_; /* thread currently applying, 0 if idle */ + +public: + wsrep_SR_trx_info(THD *thd) + { + WSREP_DEBUG("wsrep_SR_trx_info construtor: %lld", (thd) ? thd->thread_id : -1); + thd_ = thd; + applier_thread_ = 0; + thd_in_use_ = false; + preempted_ = false; + mysql_mutex_init(key_LOCK_wsrep_thd_queue, + &LOCK_wsrep_trx_info_, + MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_wsrep_thd_queue, &COND_wsrep_trx_info_, NULL); + } + + ~wsrep_SR_trx_info() + { + WSREP_DEBUG("wsrep_SR_trx_info destructor: %lld", + (thd_) ? thd_->thread_id : -1); + remove(NULL, true); + mysql_mutex_destroy(&LOCK_wsrep_trx_info_); + mysql_cond_destroy(&COND_wsrep_trx_info_); + } + + my_thread_id get_applier_thread() { return applier_thread_; } + void set_applier_thread(my_thread_id thread_id) { applier_thread_= thread_id; } + + void remove(THD* caller, bool persistent); + void cleanup(); + + THD* get_THD() const { return thd_; } + + void append_fragment(const wsrep_trx_meta_t *trx) + { + assert(thd_); + thd_->wsrep_SR_fragments.push_back(*trx); + } + +private: + bool thd_in_use_; + mysql_mutex_t LOCK_wsrep_trx_info_; + mysql_cond_t COND_wsrep_trx_info_; + +public: + void acquire() + { + wsp::auto_lock lock(&LOCK_wsrep_trx_info_); + assert(!thd_in_use_); + thd_in_use_ = true; + } + + void release() + { + wsp::auto_lock lock(&LOCK_wsrep_trx_info_); + assert(thd_in_use_); + thd_in_use_ = false; + mysql_cond_signal(&COND_wsrep_trx_info_); + } + + void wait_release() + { + wsp::auto_lock lock(&LOCK_wsrep_trx_info_); + while (thd_in_use_) + { + mysql_cond_wait(&COND_wsrep_trx_info_, + &LOCK_wsrep_trx_info_); + } + } + +private: + bool preempted_; + +public: + /* + * These methods should be accessed only through SR_pool, + * concurrent access is prevented by LOCK_wsrep_SR_pool. + */ + void mark_preempted() + { + preempted_ = true; + } + + bool preempted() const + { + return preempted_; + } +}; + +class SR_pool +{ + /* protected by LOCK_wsrep_SR_pool mutex */ + // ideally we want to change std::map to std::unordered_map here + typedef std::map<uint64_t, wsrep_SR_trx_info*> trx_pool_t; + typedef std::map<wsrep_uuid_t, trx_pool_t> src_pool_t; + private: + src_pool_t pool_; + public: + SR_pool() { } + + ~SR_pool () { + WSREP_DEBUG("SR_pool destructor"); + } + + wsrep_SR_trx_info* find(const wsrep_uuid_t& nodeID, + const uint64_t& trxID) const; + wsrep_SR_trx_info* add(const wsrep_uuid_t& nodeID, const uint64_t& trxID, + THD *thd); + void remove(THD* caller, const wsrep_uuid_t& nodeID, const uint64_t& trxID, + bool persistent); + void removeAll(THD* caller, bool persistent); + void trimToNodes (THD* caller, const wsrep_member_info_t nodes[], int nodeCount); + + /* + * Mark the corresponding SR trx in the pool as preempted. + * Once preempted appliers are no longer able to find the + * trx through SR_pool::find(), and can no longer remove + * it using SR_pool::remove(). + * The caller takes responsibility of removing the trx from + * the pool by using SR_pool::wait_release_and_remove(). + */ + bool preempt(THD* thd); + + /* + * Waits until the corresponding trx is released by applier + * and removes it from the pool. Caller must first call + * SR_pool::preempt() on the same thd. + */ + bool wait_release_and_remove(THD* caller, THD *thd); +}; + +class Wsrep_schema; + +class SR_storage +{ +public: + SR_storage() + : + cluster_uuid_(), + restored_(false) + { } + virtual ~SR_storage() {} + + virtual int init(const char* cluster_uuid_str, Wsrep_schema*) = 0; + + virtual THD* append_frag (THD* thd, + uint32_t flags, + const uchar* buf, + size_t buf_len) = 0; + + virtual void update_frag_seqno (THD* thd, THD* orig_THD) = 0; + + virtual void release_SR_thd(THD* thd) = 0; + + virtual void append_frag_apply (THD* thd, + uint32_t flags, + const uchar* buf, + size_t buf_len) = 0; + + virtual void append_frag_commit (THD* thd, + uint32_t flags, + const uchar* buf, + size_t buf_len) = 0; + + virtual void remove_trx ( THD* thd ) = 0; + + virtual void remove_trx ( wsrep_SR_trx_info* trx ) = 0; + + virtual void rollback_trx ( THD* thd ) = 0; + + virtual void rollback_trx ( wsrep_SR_trx_info* trx ) = 0; + + virtual void trx_done ( THD* thd ) = 0; + + virtual int replay_trx(THD* thd, const wsrep_trx_meta_t& meta) = 0; + + virtual int restore( THD *thd ) = 0; + + virtual void prepare_for_open_tables(THD *thd, TABLE_LIST **table_list) = 0; + + virtual void close() = 0; + +protected: + wsrep_uuid_t cluster_uuid_; + bool restored_; +}; + +/* functions for appliers */ +extern SR_pool *sr_pool; + +void wsrep_close_SR_transactions(THD *thd); +void wsrep_init_SR_pool(); +void wsrep_restore_SR_trxs(THD *thd); +void trim_SR_pool(THD* thd, const wsrep_member_info_t nodes[], int nodeCount); + +/* functions for rollbacker */ +bool wsrep_preempt_SR_THD(THD* victim_thd); +bool wsrep_abort_SR_THD(THD* thd, THD* victim_thd); + +/* + Remove SR fragments from SR storage. This happens in the thd + transaction context, fragment removal will be committed + at the same time as THD transaction is committed. + */ +void wsrep_remove_SR_fragments(THD *thd); + +/* + Rollback SR trx. Removes fragments from SR storage non-transactionally, + so it can be used outside of THD transaction context. + */ +void wsrep_rollback_SR_trx(THD *thd); + +/* + Prepare SR trx info for local transaction. Transfers SR ownership + to SR trx info handle. + */ +void wsrep_prepare_SR_trx_info_for_rollback(THD *thd); + +static inline bool wsrep_may_produce_SR_step(const THD *thd) +{ + switch (thd->lex->sql_command) + { + case SQLCOM_INSERT: + case SQLCOM_INSERT_SELECT: + case SQLCOM_REPLACE: + case SQLCOM_REPLACE_SELECT: + case SQLCOM_UPDATE: + case SQLCOM_UPDATE_MULTI: + case SQLCOM_DELETE: + case SQLCOM_LOAD: + case SQLCOM_COMMIT: + case SQLCOM_ROLLBACK_TO_SAVEPOINT: + case SQLCOM_SAVEPOINT: + return true; + default: + return false; + } +} + +void wsrep_prepare_SR_for_open_tables(THD *thd, TABLE_LIST **table_list); +void wsrep_handle_SR_rollback(void *BF_thd_ptr, void *victim_thd_ptr); + +#endif /* WSREP_SR_H */ diff --git a/sql/wsrep_sr_file.cc b/sql/wsrep_sr_file.cc new file mode 100644 index 00000000000..7745b759349 --- /dev/null +++ b/sql/wsrep_sr_file.cc @@ -0,0 +1,563 @@ +/* Copyright (C) 2013 Codership Oy <info@codership.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + +#include <my_global.h> +#include "my_pthread.h" +#include "wsrep_priv.h" +#include "wsrep_api.h" +#include "wsrep_sr_file.h" +#include "wsrep_applier.h" // wsrep_apply() +#include "wsrep_thd.h" +#include "wsrep_utils.h" +#include <map> +#include <string> +#include <ostream> +#include <iostream> +#include <fstream> +#include <list> +#include <dirent.h> +#include <sstream> +#include <iomanip> + +/* to prepare wsrep_uuid_t usable in std::map */ +inline bool operator==(const node_trx_t& lhs, const node_trx_t& rhs) { + return(memcmp(lhs.data, rhs.data, 24) == 0); +} +inline bool operator!=(const node_trx_t& lhs, const node_trx_t& rhs) { + return !operator==(lhs,rhs); +} +inline bool operator< (const node_trx_t& lhs, const node_trx_t& rhs) { + return(memcmp(lhs.data, rhs.data, 24) < 0); +} +inline bool operator> (const node_trx_t& lhs, const node_trx_t& rhs) { + return operator< (rhs,lhs); +} +inline bool operator<=(const node_trx_t& lhs, const node_trx_t& rhs) { + return !operator> (lhs,rhs); +} +inline bool operator>=(const node_trx_t& lhs, const node_trx_t& rhs) { + return !operator< (lhs,rhs); +} + +typedef std::map<uint64_t, std::vector<unsigned char> > frag_list_t; +typedef std::map<node_trx_t, frag_list_t> db_t; + +class SR_file { + std::string const name_; + std::ofstream outfile_; + + size_t size_; + long frags_; + int const order_; + + typedef std::map<node_trx_t, bool> trxs_t; + trxs_t trxs_; + + /* will go in file header */ + signed long long min_seqno_; + signed long long max_seqno_; + +public: + SR_file(std::string name, int order) : + name_(name), + order_(order) + { + outfile_.open(name.c_str(), std::ios::out | std::ios::app | std::ios::binary ); + size_ = 0; + min_seqno_ = 0; + max_seqno_ = 0; + } + SR_file() : order_(0) + { + } + int get_order() { return order_; } + std::string get_name() { return name_; } + + void write_file_header(); + void read_file_header(); + void write_frag_header( + wsrep_uuid_t *node_uuid, + wsrep_trx_id_t trx, + wsrep_seqno_t seqno, + uint32_t flags) + { + char uuid_str[37] = {'\0',}; + wsrep_uuid_print(node_uuid, uuid_str, 37); + + outfile_ << uuid_str; + outfile_ << ' ' << trx << ' ' << seqno; + + if (flags & WSREP_FLAG_TRX_START) { + outfile_ << 'B'; + } else { + outfile_ << ' '; + } + if (flags & WSREP_FLAG_TRX_END) { + outfile_ << 'C'; + } else { + outfile_ << ' '; + } + if (flags & WSREP_FLAG_ROLLBACK) { + outfile_ << 'R'; + } else { + outfile_ << ' '; + } + } + void append(wsrep_uuid_t *node_uuid, + wsrep_trx_id_t trx, + wsrep_seqno_t seqno, + uint32_t flags, + const uchar *buf, + size_t buf_len) + { + if (seqno < min_seqno_ || min_seqno_ == 0) min_seqno_ = seqno; + if (seqno > max_seqno_ || max_seqno_ == 0) max_seqno_ = seqno; + + write_frag_header(node_uuid, trx, seqno, flags); + outfile_ << buf_len << '#'; + outfile_.write((char*)(buf), buf_len); + size_ += buf_len; + size_ += 35; /* for header */ + + node_trx_t trxid = { {'\0',} }; + memcpy(trxid.data, node_uuid->data, 16); + sprintf((char*)&(trxid.data[16]), "%ld", trx); + trxs_[trxid] = true; + }; + + bool remove(const wsrep_uuid_t *node_uuid, + const wsrep_seqno_t seqno) + { + node_trx_t trxid = { {'\0',} }; + memcpy(trxid.data, node_uuid->data, 16); + sprintf((char*)&(trxid.data[16]), "%ld", seqno); + + //std::string trxid = node_uuid + std::to_string(seqno); + trxs_[trxid] = false; + + /* check if all transactions are over in this file */ + bool all_gone(true); + + trxs_t::iterator iterator; + for(iterator = trxs_.begin(); iterator != trxs_.end(); iterator++) { + if (iterator->second == true) + { + all_gone = false; + continue; + } + } + + return all_gone; + } + + size_t size() + { + return size_; + } + + class File_hdr { + }; + + class Frag_hdr { + }; + + void close() + { + outfile_.close(); + } +}; + +int SR_storage_file::max_file_order() +{ + int max = 0; + std::list<SR_file*>::iterator iterator; + for (iterator = files_.begin(); iterator != files_.end(); ++iterator) { + if ((*iterator)->get_order() > max) max = (*iterator)->get_order(); + } + return max; +} + +std::string *SR_storage_file::new_name(int order) +{ + std::string *name = new std::string(dir_); + *name += "/wsrep_SR_"; + *name += order; + *name += ".dat"; + return name; +} + +SR_file *SR_storage_file::append_file() { + + int order = max_file_order() + 1; + std::stringstream ss; + ss << dir_ << "/wsrep_SR_store." << order; + SR_file *file = new SR_file(ss.str(), order); + files_.push_back(file); + return file; +} + +void SR_storage_file::remove_file(SR_file *file) { + remove(file->get_name().c_str()); + delete file; +} + +SR_storage_file::SR_storage_file( + const char *dir, + size_t limit, + const char * cluster_uuid_str) +{ + dir_ = std::string(dir); + size_limit_ = limit; + wsrep_uuid_scan(cluster_uuid_str, 37, &cluster_uuid_); + restored_ = false; + + curr_file_ = NULL; + + WSREP_DEBUG("SR pool initialized, group: %s", cluster_uuid_str); +} + +int SR_storage_file::init(const char* cluster_uuid_str, Wsrep_schema* unused) +{ + int rcode = 0; + + WSREP_DEBUG("SR pool initialized,"); + WSREP_DEBUG("cluster_uuid:str: %s", cluster_uuid_str); + wsrep_uuid_scan(cluster_uuid_str, 37, &cluster_uuid_); + + return rcode; +} + +THD* SR_storage_file::append_frag(THD* thd, + uint32_t flags, + const uchar* buf, + size_t buf_len) +{ + wsrep_uuid_t *node_uuid = &(thd->wsrep_trx_meta.stid.node); + wsrep_trx_id_t trx = thd->wsrep_trx_meta.stid.trx; + wsrep_seqno_t seqno = thd->wsrep_trx_meta.gtid.seqno; + + if (!restored_) return NULL; + + wsp::auto_lock lock(&LOCK_wsrep_SR_store); + + if (!curr_file_) curr_file_ = append_file(); + + assert(curr_file_); + + curr_file_->append(node_uuid, trx, seqno, flags, buf, buf_len); + + if (curr_file_->size() > size_limit_) + { + curr_file_->close(); + curr_file_ = NULL; + } + + return NULL; +} + +void SR_storage_file::remove_trx( THD *thd ) +{ + assert (thd); + const wsrep_uuid_t *node_uuid = &(thd->wsrep_trx_meta.stid.node); + const wsrep_trx_id_t trxid = thd->wsrep_trx_meta.stid.trx; + + /* remove from all SR files */ + wsp::auto_lock lock(&LOCK_wsrep_SR_store); + + std::list<SR_file*>::iterator iterator; + for (iterator = files_.begin(); iterator != files_.end();) { + if ((*iterator)->remove(node_uuid, trxid)) + { + if (curr_file_ == *iterator) curr_file_ = NULL; + + remove_file(*iterator); + + std::list<SR_file*>::iterator prev = iterator++; + files_.erase(prev); + } + else + { + ++iterator; + } + } +} + +void SR_storage_file::rollback_trx( THD* thd ) + +{ + WSREP_DEBUG("SR_storage_file::commit_trx"); + remove_trx(thd); +} + +int SR_storage_file::replay_trx(THD* thd, const wsrep_trx_meta_t& meta) +{ + WSREP_ERROR("SR_storage_file::replay_trx not implemented"); + return 1; +} + + +void SR_storage_file::read_trxs_from_file( + std::string file, trxs_t *trxs, THD *thd, enum read_mode mode) +{ + std::ifstream infile; + + WSREP_DEBUG("read_trxs_from_file"); + + if (!strcmp(file.c_str(), "---")) + { + WSREP_DEBUG("SR file comment line skipped"); + return; + } + infile.open(file.c_str(), std::ios::in | std::ios::binary); + infile.exceptions ( + std::ifstream::failbit | std::ifstream::badbit | std::ifstream::eofbit); + + try { + + while (infile.good()) + { + char uuid[37] = {'\0',}; + wsrep_uuid_t node_uuid; + wsrep_trx_id_t trxid; + wsrep_seqno_t seqno; + char begin = '#'; + char commit = '#'; + char rollback = '#'; + int len; + char *buf; + + /* 1 source node UUID */ + if (infile.get(uuid, 37)) + { + wsrep_uuid_scan(uuid, 37, &node_uuid); + } + else + break; + + /* 2 source node trx ID */ + infile >> trxid; + + /* 3 trx seqno */ + infile >> seqno; + + /* 4 flags: Begin-Commit-Rollback */ + begin = (char)infile.get(); + commit = (char)infile.get(); + rollback = (char)infile.get(); + + /* 5 rbr buffer length */ + infile >> len; + + /* # after header part */ + if ( (char)infile.get() != '#') + { + WSREP_WARN("SR frament file bad line: %s %ld %ld %c %c %c", + uuid, trxid, seqno, begin, commit, rollback); + return; + } + + /* 6 the buffer */ + buf = new char [len]; + infile.read(buf, len); + + /* */ + node_trx_t nodetrx; + memcpy(nodetrx.data, node_uuid.data, 16); + sprintf((char*)&(nodetrx.data[16]), "%ld", trxid); + + int flags = 0; + wsrep_trx_meta_t meta; + meta.gtid.uuid = cluster_uuid_; + meta.gtid.seqno = seqno; + meta.stid.node = node_uuid; + meta.stid.trx = trxid; + + if (begin == 'B') + { + if (mode == FILTER) + { + WSREP_DEBUG("new trx in SR file: trx %ld seqno %ld", trxid, seqno); + (*trxs)[nodetrx] = true; + } + else + { + flags |= WSREP_FLAG_TRX_START; + } + } + else if (!(*trxs)[nodetrx]) + { + WSREP_WARN("unfinished trx in SR file: trx %ld seqno %ld", + trxid, seqno); + } + + if (mode == FILTER && (commit == 'C' || rollback == 'R')) + { + WSREP_DEBUG("trx commit in SR file: trx %ld seqno %ld", trxid, seqno); + (*trxs)[nodetrx] = false; + } + + if (mode == POPULATE && (*trxs)[nodetrx]) + { + /* pending transaction to launch in sr_pool */ + WSREP_DEBUG("launching SR trx: %ld", trxid); + + wsrep_buf_t const ws= { buf, size_t(len) }; + wsrep_apply_error err; + if (wsrep_apply(thd, flags, &ws, &meta, err) != + WSREP_CB_SUCCESS) + { + WSREP_WARN("Streaming Replication fragment restore failed: %s", + err.c_str() ? err.c_str() : "(null)"); + return; + } + DBUG_ASSERT(err.is_null()); + } + else if (mode == POPULATE) + WSREP_DEBUG("not populating trx %ld seqno %ld", trxid, seqno); + + delete[] buf; + } + } + catch(std::exception e) + { + if(infile.eof()) + { + WSREP_DEBUG("infile EOF"); + } + else + WSREP_DEBUG("infile exception"); + } +} + +int SR_storage_file::restore( THD *thd ) +{ + std::ifstream infile; + std::string file(dir_ + '/' + "wsrep_SR_info"); + THD * SRthd = NULL; + + char cluster_uuid_str[37] = {'\0',}; + + wsp::auto_lock lock(&LOCK_wsrep_SR_store); + + if (restored_) + { + return 0; + } + wsrep_uuid_print(&cluster_uuid_, cluster_uuid_str, 37); + + WSREP_DEBUG("SR pool restore, group %s", cluster_uuid_str); + + /* read SR store info */ + infile.open(file.c_str(), std::ios::in); + if (infile.is_open()) + { + std::string line; + getline (infile, line); + + /* this should be cluster uuid */ + if (line.length() != 36) + { + WSREP_WARN("Streaming Replication info file is corrupted"); + restored_ = true; + return -1; + } + + if (strncmp(cluster_uuid_str, line.c_str(), 36)) { + WSREP_WARN("Streaming Replication cluster uuid has changed, \n" + "cluster in SR file: %s\n" + "current cluster: %s", + line.c_str(), cluster_uuid_str); + restored_ = true; + return -2; + } + + trxs_t trxs; + + bool thd_started = false; + if (!thd) + { + SRthd = wsrep_start_SR_THD((char*)&infile); + SRthd->wsrep_SR_thd = false; + thd_started = true; + SRthd->store_globals(); + } + else + { + SRthd = thd; + } + + /* read all fragment files, and filter out committed trxs */ + while ( getline (infile, line) && strcmp(line.c_str(), "---")) + { + WSREP_DEBUG("SR file filtering line: %s", line.c_str()); + read_trxs_from_file(line, &trxs, SRthd, FILTER); + } + /* read again, and populate pending trxs */ + infile.seekg(infile.beg); + getline (infile, line); + + while ( getline (infile, line) ) + { + WSREP_DEBUG("SR file populating line: %s", line.c_str()); + read_trxs_from_file(line, &trxs, SRthd, POPULATE); + } + infile.close(); + if (thd_started) + { + wsrep_end_SR_THD(SRthd); + } + else + { + thd->store_globals(); + } + } + + restored_ = true; + remove(file.c_str()); + return 0; +} + +void SR_storage_file::close() +{ + WSREP_DEBUG("SR_storage_file::close()"); + wsp::auto_lock lock(&LOCK_wsrep_SR_store); + + /* write store info */ + std::string file(dir_ + '/' + "wsrep_SR_info"); + std::ofstream srinfo; + char cluster_uuid_str[37] = {'\0',}; + + wsrep_uuid_print(&cluster_uuid_, cluster_uuid_str, 37); + + srinfo.open(file.c_str()); + srinfo << cluster_uuid_str << '\n'; + + /* close transactions */ + std::list<SR_file*>::iterator iterator; + for (iterator = files_.begin(); iterator != files_.end();) + { + std::list<SR_file*>::iterator prev = iterator++; + WSREP_DEBUG("Closing streaming replication file: %s", + (*prev)->get_name().c_str()); + + srinfo << (*prev)->get_name() << '\n'; + (*prev)->close(); + } + srinfo << "---" << '\n'; + + srinfo.close(); + + restored_ = false; +} diff --git a/sql/wsrep_sr_file.h b/sql/wsrep_sr_file.h new file mode 100644 index 00000000000..123499cb5a2 --- /dev/null +++ b/sql/wsrep_sr_file.h @@ -0,0 +1,111 @@ +/* Copyright (C) 2013 Codership Oy <info@codership.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + +#include "wsrep_priv.h" + +#include "wsrep_sr.h" +#include "wsrep_thd.h" +#include <map> +#include <string> +#include <list> + +class SR_storage; +class SR_file; +class Wsrep_schema; + +typedef struct node_trx { + uint8_t data[24]; +} node_trx_t; +typedef std::map<node_trx_t, bool> trxs_t; + +class SR_storage_file: public SR_storage { + enum read_mode { + FILTER, + POPULATE + }; + + private: + + //wsrep_uuid_t cluster_uuid_; + std::string dir_; + size_t size_limit_; + + std::list<SR_file*> files_; + + SR_file *curr_file_; + + int max_file_order(); + std::string *new_name(int order); + SR_file *append_file(); + void remove_file(SR_file *file); + + void read_trxs_from_file( + std::string file, + trxs_t *trxs, + THD *thd, + enum read_mode mode); + + public: + SR_storage_file(const char *dir, size_t limit, const char* cluster_uuid_str); + + int init(const char *cluster_uuid_str, Wsrep_schema*); + + THD* append_frag(THD* thd, + uint32_t flags, + const uchar* buf, + size_t buf_len); + + void append_frag_apply(THD* thd, + uint32_t flags, + const uchar* buf, + size_t buf_len) + { + append_frag(thd, flags, buf, buf_len); + } + + void append_frag_commit(THD* thd, + uint32_t flags, + const uchar* buf, + size_t buf_len) + { + append_frag(thd, flags, buf, buf_len); + } + + void update_frag_seqno (THD* thd, THD* orig_THD) {}; + + void release_SR_thd(THD* thd) {} + + void remove_trx( THD *thd ); + + void remove_trx( wsrep_SR_trx_info *trx ) { + remove_trx(trx->get_THD()); + } + + void rollback_trx( THD *thd ); + + void rollback_trx( wsrep_SR_trx_info *trx ) { + rollback_trx(trx->get_THD()); + } + + void trx_done( THD *thd ) { } + + int replay_trx(THD* thd, const wsrep_trx_meta_t&); + + int restore( THD *thd ); + + void prepare_for_open_tables(THD *, TABLE_LIST **) { } + + void close(); +}; diff --git a/sql/wsrep_sr_table.cc b/sql/wsrep_sr_table.cc new file mode 100644 index 00000000000..bbde72fc30c --- /dev/null +++ b/sql/wsrep_sr_table.cc @@ -0,0 +1,223 @@ +/* Copyright (C) 2013 Codership Oy <info@codership.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + +#include <my_global.h> +#include "my_pthread.h" +#include "wsrep_priv.h" +#include "wsrep_sr_table.h" +#include "wsrep_schema.h" + +#include "sql_class.h" + + +SR_storage_table::SR_storage_table() + : + wsrep_schema_(0) +{ +} + +SR_storage_table::~SR_storage_table() +{ +} + +int SR_storage_table::init(const char* cluster_uuid_str, + Wsrep_schema* wsrep_schema) +{ + /* Storage tables have been created by Wsrep_schema */ + wsrep_schema_= wsrep_schema; + return 0; +} + + +THD* SR_storage_table::append_frag(THD* thd, + uint32_t flags, + const uchar* buf, + size_t buf_len) +{ + /* + During restore phase fragments are read from storage, don't + append back. + */ + if (restored_ == false) { + return NULL; + } + + thd->wsrep_trx_meta.stid.trx = thd->wsrep_ws_handle.trx_id; + + THD* ret = wsrep_schema_->append_frag(thd->wsrep_trx_meta, flags, + buf, buf_len); + if (!ret) { + WSREP_ERROR("Failed to append frag to persistent storage"); + } + else { + WSREP_DEBUG("SR_storage_table::append_frag(): thd %lld, seqno %lld, " + "trx_id: %ld, thd_ret: %p", + thd->thread_id, (long long)thd->wsrep_trx_meta.gtid.seqno, + thd->wsrep_trx_meta.stid.trx, ret); + } + + thd->store_globals(); /* Restore original thread context */ + return ret; +} + +void SR_storage_table::update_frag_seqno(THD* thd, THD* orig_THD) +{ + thd->store_globals(); + + if (wsrep_schema_->update_frag_seqno(thd, orig_THD->wsrep_trx_meta)) { + WSREP_ERROR("Failed to update seqno, must abort"); + unireg_abort(1); + } + + orig_THD->wsrep_SR_fragments.push_back(orig_THD->wsrep_trx_meta); + orig_THD->store_globals(); /* Restore original thread context */ +} + +void SR_storage_table::release_SR_thd(THD* thd) +{ + thd->store_globals(); + wsrep_schema_->release_SR_thd(thd); +} + +void SR_storage_table::append_frag_apply(THD* thd, + uint32_t flags, + const uchar* buf, + size_t buf_len) +{ + /* + During restore phase fragments are read from storage, don't + append back. + */ + if (restored_ == false) { + return; + } + + if (wsrep_schema_->append_frag_apply(thd, thd->wsrep_trx_meta, flags, + buf, buf_len)) { + WSREP_ERROR("Failed to append frag to persistent storage, must abort"); + unireg_abort(1); + } + + thd->store_globals(); /* Restore original thread context */ +} + +void SR_storage_table::append_frag_commit(THD* thd, + uint32_t flags, + const uchar* buf, + size_t buf_len) +{ + /* + During restore phase fragments are read from storage, don't + append back. + */ + if (restored_ == false) { + return; + } + + if (wsrep_schema_->append_frag_commit(thd->wsrep_trx_meta, flags, + buf, buf_len)) { + WSREP_ERROR("Failed to append frag to persistent storage, must abort"); + unireg_abort(1); + } + + thd->wsrep_SR_fragments.push_back(thd->wsrep_trx_meta); + thd->store_globals(); /* Restore original thread context */ +} + +void SR_storage_table::remove_trx(THD* thd) +{ + WSREP_DEBUG("SR_storage_table::remove_trx(%lld) seqno %lld, trx %ld", + thd->thread_id, (long long)thd->wsrep_trx_meta.gtid.seqno, + thd->wsrep_trx_meta.stid.trx); + int err= wsrep_schema_->remove_trx(thd, &thd->wsrep_SR_fragments); + if (err == -1) { + WSREP_DEBUG("SR_storage_table::remove_trx() interrupted"); + } else if (err) { + WSREP_WARN("Failed to delete fragments from persistent storage"); + } +} + +void SR_storage_table::remove_trx(wsrep_SR_trx_info* trx) +{ + remove_trx(trx->get_THD()); +} + +void SR_storage_table::rollback_trx(THD* thd) +{ + WSREP_DEBUG("SR_storage_table::rollback_trx(%lld) seqno %lld, trx %ld", + thd->thread_id, (long long)thd->wsrep_trx_meta.gtid.seqno, + thd->wsrep_trx_meta.stid.trx); + int err= wsrep_schema_->rollback_trx(thd); + if (err == -1) { + WSREP_DEBUG("SR_storage_table::rollback_trx() interrupted"); + } else if (err) { + WSREP_WARN("Failed to delete fragments from persistent storage"); + } + thd->store_globals(); /* Restore original thread context */ +} + +void SR_storage_table::rollback_trx(wsrep_SR_trx_info* trx) +{ + rollback_trx(trx->get_THD()); +} + +void SR_storage_table::trx_done(THD* thd) +{ + if (thd->wsrep_conflict_state() != MUST_REPLAY) + thd->wsrep_SR_fragments.clear(); +} + +int SR_storage_table::replay_trx(THD* thd, const wsrep_trx_meta_t& meta) +{ + return wsrep_schema_->replay_trx(thd, meta); +} + +int SR_storage_table::restore(THD* thd) +{ + if (restored_ == true) { + WSREP_DEBUG("SR_storage_table::restore: Already restored"); + return 0; + } + + WSREP_INFO("SR_storage_table::restore"); + int ret= wsrep_schema_->restore_frags(); + if (thd) { + thd->store_globals(); + } + else { + my_pthread_setspecific_ptr(THR_THD, NULL); + } + restored_= true; + return ret; +} + +void SR_storage_table::prepare_for_open_tables(THD *thd, TABLE_LIST **table_list) +{ + wsrep_schema_->init_SR_table(&thd->wsrep_SR_table); + TABLE_LIST *ptr= *table_list; + if (!ptr) + { + *table_list= &thd->wsrep_SR_table; + } + else + { + while (ptr->next_global) ptr = ptr->next_global; + ptr->next_global = &thd->wsrep_SR_table; + } +} + +void SR_storage_table::close() +{ +} diff --git a/sql/wsrep_sr_table.h b/sql/wsrep_sr_table.h new file mode 100644 index 00000000000..9cc36f21854 --- /dev/null +++ b/sql/wsrep_sr_table.h @@ -0,0 +1,67 @@ +/* Copyright (C) 2013 Codership Oy <info@codership.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + + +#include "wsrep_sr.h" + +class Wsrep_schema; + +class SR_storage_table : public SR_storage +{ + public: + SR_storage_table(); + ~SR_storage_table(); + int init(const char *cluster_uuid_str, Wsrep_schema*); + + THD* append_frag(THD* thd, + uint32_t flags, + const uchar* buf, + size_t buf_len); + + void update_frag_seqno(THD* thd, THD* orig_THD); + + void release_SR_thd(THD* thd); + + void append_frag_apply(THD* thd, + uint32_t flags, + const uchar* buf, + size_t buf_len); + + void append_frag_commit(THD* thd, + uint32_t flags, + const uchar* buf, + size_t buf_len); + + void remove_trx( THD *thd ); + + void remove_trx( wsrep_SR_trx_info *trx ); + + void rollback_trx( THD *thd ); + + void rollback_trx( wsrep_SR_trx_info *trx ); + + void trx_done( THD *thd ); + + int replay_trx(THD* thd, const wsrep_trx_meta_t& meta); + + int restore( THD *thd ); + + void prepare_for_open_tables(THD *thd, TABLE_LIST **table_list); + + void close(); + + private: + Wsrep_schema* wsrep_schema_; +}; diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index d5b0344c456..fff7e747f9b 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -1,4 +1,4 @@ -/* Copyright 2008-2015 Codership Oy <http://www.codership.com> +/* Copyright 2008-2017 Codership Oy <http://www.codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,9 +28,10 @@ #include "wsrep_xid.h" #include <cstdio> #include <cstdlib> - #include <my_service_manager.h> +const char wsrep_defaults_group_suffix[256] = {0}; + static char wsrep_defaults_file[FN_REFLEN * 2 + 10 + 30 + sizeof(WSREP_SST_OPT_CONF) + sizeof(WSREP_SST_OPT_CONF_SUFFIX) + @@ -271,7 +272,8 @@ void wsrep_sst_complete (const wsrep_uuid_t* sst_uuid, true Error */ -bool wsrep_sst_received (wsrep_t* const wsrep, +void wsrep_sst_received (THD* thd, + wsrep_t* const wsrep, const wsrep_uuid_t& uuid, const wsrep_seqno_t seqno, const void* const state, @@ -284,81 +286,68 @@ bool wsrep_sst_received (wsrep_t* const wsrep, OK from wsrep provider. By doing so, the values remain consistent across the server & wsrep provider. */ - bool do_update= false; - - // Get the locally stored uuid:seqno. - if (wsrep_get_SE_checkpoint(local_uuid, local_seqno)) - { - return true; - } + /* + TODO: Handle backwards compatibility. WSREP API v25 does not have + wsrep schema. + */ + /* + If thd is non-NULL, this thread is holding LOCK_global_system_variables. + It needs to be released temporarily since wsrep_init_schema() + does THD pool initialization, which will lock this lock in + THD allocation. + */ + //if (thd) mysql_mutex_unlock(&LOCK_global_system_variables); + wsrep_init_schema(); + /* + Logical SST methods (mysqldump etc) don't update InnoDB sys header. + Reset the SE checkpoint before recovering view in order to avoid + sanity check failure. + */ + if (!wsrep_before_SE()) { + wsrep_seqno_t se_seqno= -1; + wsrep_uuid_t se_uuid= WSREP_UUID_UNDEFINED; + wsrep_set_SE_checkpoint(se_uuid, se_seqno); + wsrep_set_SE_checkpoint(uuid, seqno); + } + wsrep_verify_SE_checkpoint(uuid, seqno); + wsrep_init_SR(); + //if (thd) mysql_mutex_lock(&LOCK_global_system_variables); - if (memcmp(&local_uuid, &uuid, sizeof(wsrep_uuid_t)) || - local_seqno < seqno) - { - do_update= true; - } - else if (local_seqno > seqno) - { - WSREP_WARN("SST position can't be set in past. Requested: %lld, Current: " - " %lld.", (long long)seqno, (long long)local_seqno); /* - If we are here because of SET command, simply return true (error) instead of - aborting. + Both wsrep_init_SR() and wsrep_recover_view() may use + wsrep thread pool. Restore original thd context before returning. */ - if (implicit) - { - WSREP_WARN("Can't continue."); - unireg_abort(1); + if (thd) { + thd->store_globals(); } - else - { - return true; + else { + my_pthread_setspecific_ptr(THR_THD, NULL); } - } #ifdef GTID_SUPPORT wsrep_init_sidno(uuid); #endif /* GTID_SUPPORT */ - if (wsrep) - { - int const rcode(seqno < 0 ? seqno : 0); - wsrep_gtid_t const state_id= {uuid, - (rcode ? WSREP_SEQNO_UNDEFINED : seqno)}; - - wsrep_status_t ret= wsrep->sst_received(wsrep, &state_id, state, - state_len, rcode); - - if (ret != WSREP_OK) + if (wsrep) { - return true; - } - } + int const rcode(seqno < 0 ? seqno : 0); + wsrep_gtid_t const state_id = { + uuid, (rcode ? WSREP_SEQNO_UNDEFINED : seqno) + }; - // Now is the good time to update the local state and checkpoint. - if (do_update) - { - if (wsrep_set_SE_checkpoint(uuid, seqno)) - { - return true; + wsrep_buf_t const st= { state, state_len }; + wsrep->sst_received(wsrep, &state_id, &st, rcode); } - - local_uuid= uuid; - local_seqno= seqno; - } - - return false; } // Let applier threads to continue -bool wsrep_sst_continue () +void wsrep_sst_continue () { if (sst_needed) { WSREP_INFO("Signalling provider to continue."); - return wsrep_sst_received (wsrep, local_uuid, local_seqno, NULL, 0, true); + wsrep_sst_received (0, wsrep, local_uuid, local_seqno, NULL, 0, true); } - return false; } struct sst_thread_arg @@ -719,7 +708,12 @@ static ssize_t sst_prepare_mysqldump (const char* addr_in, return ret; } -static bool SE_initialized = false; +static enum +{ + WSREP_SE_UNINITIALIZED, + WSREP_SE_INITIALIZED, + WSREP_SE_INIT_ERROR +} SE_init_status; ssize_t wsrep_sst_prepare (void** msg) { @@ -733,7 +727,7 @@ ssize_t wsrep_sst_prepare (void** msg) if (!msg) { WSREP_ERROR("Could not allocate %zd bytes for state request", ret); - unireg_abort(1); + ret= -ENOMEM; } return ret; } @@ -760,7 +754,7 @@ ssize_t wsrep_sst_prepare (void** msg) { WSREP_ERROR("Could not parse wsrep_node_address : %s", wsrep_node_address); - unireg_abort(1); + return -ENXIO; /* No such device or address */ } memcpy(ip_buf, addr.get_address(), addr.get_address_len()); addr_in= ip_buf; @@ -786,12 +780,17 @@ ssize_t wsrep_sst_prepare (void** msg) if (!strcmp(wsrep_sst_method, WSREP_SST_MYSQLDUMP)) { addr_len= sst_prepare_mysqldump (addr_in, &addr_out); - if (addr_len < 0) unireg_abort(1); + if (addr_len < 0) + { + WSREP_ERROR("Failed to prepare for '%s' SST. Unrecoverable.", + wsrep_sst_method); + return addr_len; + } } else { /*! A heuristic workaround until we learn how to stop and start engines */ - if (SE_initialized) + if (SE_init_status == WSREP_SE_INITIALIZED) { // we already did SST at initializaiton, now engines are running // sql_print_information() is here because the message is too long @@ -813,12 +812,12 @@ ssize_t wsrep_sst_prepare (void** msg) { WSREP_ERROR("Failed to prepare for '%s' SST. Unrecoverable.", wsrep_sst_method); - unireg_abort(1); + return addr_len; } } size_t const method_len(strlen(wsrep_sst_method)); - size_t const msg_len (method_len + addr_len + 2 /* + auth_len + 1*/); + size_t msg_len (method_len + addr_len + 2 /* + auth_len + 1*/); *msg = malloc (msg_len); if (NULL != *msg) { @@ -832,7 +831,8 @@ ssize_t wsrep_sst_prepare (void** msg) else { WSREP_ERROR("Failed to allocate SST request of size %zu. Can't continue.", msg_len); - unireg_abort(1); + msg_len= -ENOMEM; + } if (addr_out != addr_in) /* malloc'ed */ free ((char*)addr_out); @@ -903,6 +903,11 @@ static int sst_donate_mysqldump (const char* addr, return -ENOMEM; } + /* + we enable new client connections so that mysqldump donation can connect in, + but we reject local connections from modifyingcdata during SST, to keep + data intact + */ if (!bypass && wsrep_sst_donor_rejects_queries) sst_reject_queries(TRUE); make_wsrep_defaults_file(); @@ -935,7 +940,6 @@ static int sst_donate_mysqldump (const char* addr, wsrep_gtid_t const state_id = { *uuid, (ret ? WSREP_SEQNO_UNDEFINED : seqno)}; wsrep->sst_sent (wsrep, &state_id, ret); - return ret; } @@ -1312,18 +1316,20 @@ static int sst_donate_other (const char* method, return arg.err; } -wsrep_cb_status_t wsrep_sst_donate_cb (void* app_ctx, void* recv_ctx, - const void* msg, size_t msg_len, - const wsrep_gtid_t* current_gtid, - const char* state, size_t state_len, - bool bypass) +wsrep_cb_status_t wsrep_sst_donate_cb (void* const app_ctx, + void* const recv_ctx, + const wsrep_buf_t* const msg, + const wsrep_gtid_t* const current_gtid, + const wsrep_buf_t* const state, + bool const bypass) { /* This will be reset when sync callback is called. * Should we set wsrep_ready to FALSE here too? */ wsrep_config_state->set(WSREP_MEMBER_DONOR); + local_status.set(WSREP_MEMBER_DONOR); - const char* method = (char*)msg; + const char* method = (char*)msg->ptr; size_t method_len = strlen (method); const char* data = method + method_len + 1; @@ -1363,16 +1369,16 @@ void wsrep_SE_init_grab() if (mysql_mutex_lock (&LOCK_wsrep_sst_init)) abort(); } -void wsrep_SE_init_wait() +int wsrep_SE_init_wait() { struct timespec wtime = {WSREP_TIMEDWAIT_SECONDS, 0}; uint32 total_wtime=0; - while (SE_initialized == false) + while (SE_init_status == WSREP_SE_UNINITIALIZED) { mysql_cond_timedwait (&COND_wsrep_sst_init, &LOCK_wsrep_sst_init, &wtime); - if (!SE_initialized) + if (SE_init_status == WSREP_SE_UNINITIALIZED) { total_wtime += wtime.tv_sec; WSREP_DEBUG("Waiting for SST to complete. waited %u secs.", total_wtime); @@ -1382,6 +1388,7 @@ void wsrep_SE_init_wait() } mysql_mutex_unlock (&LOCK_wsrep_sst_init); + return !(SE_init_status == WSREP_SE_INITIALIZED); } void wsrep_SE_init_done() @@ -1392,5 +1399,15 @@ void wsrep_SE_init_done() void wsrep_SE_initialized() { - SE_initialized = true; + SE_init_status= WSREP_SE_INITIALIZED; } + +void wsrep_SE_init_failed() +{ + mysql_mutex_lock(&LOCK_wsrep_sst_init); + SE_init_status= WSREP_SE_INIT_ERROR; + mysql_cond_signal(&COND_wsrep_sst_init); + mysql_mutex_unlock(&LOCK_wsrep_sst_init); +} + + diff --git a/sql/wsrep_sst.h b/sql/wsrep_sst.h index 8bf6dc31464..aa3bcb65545 100644 --- a/sql/wsrep_sst.h +++ b/sql/wsrep_sst.h @@ -64,14 +64,20 @@ extern void wsrep_sst_grab(); /*! Init thread waits for SST completion */ extern bool wsrep_sst_wait(); /*! Signals wsrep that initialization is complete, writesets can be applied */ -extern bool wsrep_sst_continue(); +extern void wsrep_sst_continue(); extern void wsrep_sst_auth_init(); extern void wsrep_sst_auth_free(); extern void wsrep_SE_init_grab(); /*! grab init critical section */ -extern void wsrep_SE_init_wait(); /*! wait for SE init to complete */ +/*! + wait for SE init to complete + + Return zero on success, non-zero on error +*/ +extern int wsrep_SE_init_wait(); extern void wsrep_SE_init_done(); /*! signal that SE init is complte */ extern void wsrep_SE_initialized(); /*! mark SE initialization complete */ +extern void wsrep_SE_init_failed(); /*! mark SE initialization failed */ #else #define wsrep_SE_initialized() do { } while(0) diff --git a/sql/wsrep_tc.h b/sql/wsrep_tc.h new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/sql/wsrep_tc.h diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index ce6d9688cb3..489613d0c6c 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -22,12 +22,19 @@ //#include "global_threads.h" // LOCK_thread_count, etc. #include "sql_base.h" // close_thread_tables() #include "mysqld.h" // start_wsrep_THD(); - +#include "wsrep_applier.h" // start_wsrep_THD(); +#include "wsrep_sr.h" // wsrep_abort_SR_THD(); +#include "mysql/service_wsrep.h" // wsrep_thd_awake(); #include "slave.h" // opt_log_slave_updates #include "rpl_filter.h" #include "rpl_rli.h" #include "rpl_mi.h" +#include "debug_sync.h" + +static Wsrep_thd_queue* wsrep_rollback_queue = 0; +static Wsrep_thd_queue* wsrep_post_rollback_queue = 0; + #if (__LP64__) static volatile int64 wsrep_bf_aborts_counter(0); #define WSREP_ATOMIC_LOAD_LONG my_atomic_load64 @@ -46,31 +53,164 @@ int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, char *buff, var->value = (char*)&wsrep_local_bf_aborts; return 0; } +void wsrep_cleanup_transaction(THD *thd) +{ + mysql_mutex_assert_owner(&thd->LOCK_wsrep_thd); + DBUG_ENTER("wsrep_cleanup_transaction"); + if (thd->wsrep_exec_mode == REPL_RECV) return; + + DBUG_ASSERT(thd->wsrep_conflict_state() != MUST_REPLAY); + DBUG_ASSERT(thd->wsrep_SR_fragments.empty()); + + if (wsrep_SR_store) wsrep_SR_store->trx_done(thd); + if (wsrep_emulate_bin_log) wsrep_thd_binlog_trx_reset(thd); + + wsrep_reset_SR_trans(thd); + thd->wsrep_exec_mode= LOCAL_STATE; + if (thd->wsrep_conflict_state() != NO_CONFLICT) + { + /* + Catch half finished rollbacks. + */ + DBUG_ASSERT(thd->wsrep_conflict_state() == ABORTED || + thd->wsrep_conflict_state() == CERT_FAILURE); + + thd->killed= NOT_KILLED; + thd->set_wsrep_conflict_state(NO_CONFLICT); + } + + if (MUST_REPLAY != thd->wsrep_conflict_state()) + { + thd->wsrep_PA_safe= true; + thd->wsrep_ws_handle.trx_id= WSREP_UNDEFINED_TRX_ID; + thd->set_wsrep_next_trx_id(WSREP_UNDEFINED_TRX_ID); + + if (thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED) + { + thd->wsrep_last_written_gtid= thd->wsrep_trx_meta.gtid; + } + thd->wsrep_trx_meta.gtid= WSREP_GTID_UNDEFINED; + thd->wsrep_trx_meta.depends_on= WSREP_SEQNO_UNDEFINED; + thd->wsrep_affected_rows= 0; + thd->wsrep_skip_wsrep_GTID= false; + thd->wsrep_xid.null(); + } + + DBUG_VOID_RETURN; +} + +/* + Run post rollback actions. -/* must have (&thd->LOCK_thd_data) */ -void wsrep_client_rollback(THD *thd) + Assert thd->LOCK_wsrep_thd ownership + */ +void wsrep_post_rollback(THD *thd) { - WSREP_DEBUG("client rollback due to BF abort for (%lld), query: %s", - (longlong) thd->thread_id, thd->query()); + mysql_mutex_assert_owner(&thd->LOCK_wsrep_thd); - WSREP_ATOMIC_ADD_LONG(&wsrep_bf_aborts_counter, 1); + WSREP_LOG_THD(thd, NULL); + + DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT || /* voluntary */ + thd->wsrep_conflict_state() == ABORTING); /* BF abort or cert failure */ - thd->wsrep_conflict_state= ABORTING; mysql_mutex_unlock(&thd->LOCK_thd_data); - trans_rollback(thd); + + if (thd->wsrep_trx_has_seqno()) + { + if (!wsrep_gtid_mode) + { + void* ptr= NULL; + size_t len= 0; + wsrep_buf_t err= {ptr, len}; + if (wsrep->commit_order_enter(wsrep, &thd->wsrep_ws_handle, + &thd->wsrep_trx_meta)) + { + WSREP_WARN("wsrep_post_rollback: failed to enter commit order"); + } + if (wsrep->commit_order_leave(wsrep, &thd->wsrep_ws_handle, + &thd->wsrep_trx_meta, &err)) + { + WSREP_WARN("wsrep_post_rollback: failed to leave commit order"); + } + } + /* + If binlogging is on commit ordering is done when dummy + event is written into binlog + */ + else if (wsrep_write_dummy_event(thd, "rollback")) + { + WSREP_WARN("wsrep_post_rollback: failed to write dummy event"); + } + } + + if (wsrep->release(wsrep, &thd->wsrep_ws_handle)) + { + WSREP_WARN("wsrep::release fail: %llu %d", + (long long)thd->thread_id, thd->get_stmt_da()->status()); + } + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + + DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT || + thd->wsrep_conflict_state() == ABORTING); + + if (thd->wsrep_conflict_state() == NO_CONFLICT) + { + thd->set_wsrep_conflict_state(MUST_ABORT); + thd->set_wsrep_conflict_state(ABORTING); + thd->set_wsrep_conflict_state(ABORTED); + } + else + { + thd->set_wsrep_conflict_state(ABORTED); + } +} + +/* + must have (&thd->LOCK_wsrep_thd) + thd->wsrep_conflict_state must be MUST_ABORT +*/ +void wsrep_client_rollback(THD *thd, bool rollbacker) +{ + mysql_mutex_assert_owner(&thd->LOCK_wsrep_thd); + DBUG_ASSERT(thd->wsrep_conflict_state() == MUST_ABORT || + thd->wsrep_conflict_state() == CERT_FAILURE); + WSREP_DEBUG("client rollback due to BF abort for (%lld %lld), query: %s", + thd->thread_id, thd->query_id, WSREP_QUERY(thd)); + + my_atomic_add64(&wsrep_bf_aborts_counter, 1); + + /* + Rollback proccess should be fired only for threads which are not + in the process of committing. + */ + DBUG_ASSERT(thd->wsrep_query_state() != QUERY_COMMITTING); + if (rollbacker) + { + DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno == WSREP_SEQNO_UNDEFINED); + } + + thd->set_wsrep_conflict_state(ABORTING); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + if (thd->wsrep_is_streaming()) + { + WSREP_DEBUG("wsrep_client_rollback: thd: %lld fragments %zu", + thd->thread_id, thd->wsrep_SR_fragments.size()); + wsrep_SR_store->rollback_trx(thd); + thd->wsrep_SR_fragments.clear(); + } if (thd->locked_tables_mode && thd->lock) { - WSREP_DEBUG("unlocking tables for BF abort (%lld)", - (longlong) thd->thread_id); + WSREP_DEBUG("unlocking tables for BF abort (%lld)", thd->thread_id); thd->locked_tables_list.unlock_locked_tables(thd); thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); } if (thd->global_read_lock.is_acquired()) { - WSREP_DEBUG("unlocking GRL for BF abort (%lld)", - (longlong) thd->thread_id); + WSREP_DEBUG("unlocking GRL for BF abort (%lld)", thd->thread_id); thd->global_read_lock.unlock_global_read_lock(thd); } @@ -82,16 +222,50 @@ void wsrep_client_rollback(THD *thd) if (thd->get_binlog_table_maps()) { - WSREP_DEBUG("clearing binlog table map for BF abort (%lld)", - (longlong) thd->thread_id); + WSREP_DEBUG("clearing binlog table map for BF abort (%lld)", thd->thread_id); thd->clear_binlog_table_maps(); } - mysql_mutex_lock(&thd->LOCK_thd_data); - thd->wsrep_conflict_state= ABORTED; + + /* + trans_rolback() must be called after all locks are released since it + calls ha_rollback_trans() which acquires TO + */ + if (trans_rollback(thd)) + { + WSREP_WARN("client rollback failed for: %lld %lld, conf: %d", + thd->thread_id, thd->query_id, + thd->wsrep_conflict_state_unsafe()); + } + + if (rollbacker && thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED) + { + /* + Thd has been assigned seqno and it needs to release provider + resoureces. Do it in separate thread to avoid deadlocks. + */ + DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_ROLLBACK); + if (wsrep_post_rollback_queue->push_back(thd)) + { + WSREP_WARN("duplicate thd %llu for post-rollbacker", + wsrep_thd_thread_id(thd)); + } + } + + /* + If the seqno is not set there is no need for post rollback + actions. + */ + if (rollbacker /* && wsrep_thd_trx_seqno(thd) == WSREP_SEQNO_UNDEFINED */) + { + wsrep_post_rollback(thd); + } + + return; } #define NUMBER_OF_FIELDS_TO_IDENTIFY_COORDINATOR 1 #define NUMBER_OF_FIELDS_TO_IDENTIFY_WORKER 2 +//#include "rpl_info_factory.h" static rpl_group_info* wsrep_relay_group_init(const char* log_fname) { @@ -135,7 +309,7 @@ static rpl_group_info* wsrep_relay_group_init(const char* log_fname) return rgi; } -static void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow* shadow) +void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow* shadow) { shadow->options = thd->variables.option_bits; shadow->server_status = thd->server_status; @@ -164,14 +338,16 @@ static void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow* shadow) thd->variables.tx_isolation = ISO_READ_COMMITTED; thd->tx_isolation = ISO_READ_COMMITTED; - shadow->db = thd->db.str; + shadow->db = (char*)thd->db.str; shadow->db_length = thd->db.length; shadow->user_time = thd->user_time; shadow->row_count_func= thd->get_row_count_func(); + shadow->user_time = thd->user_time; + thd->reset_db(&null_clex_str); } -static void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow* shadow) +void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow* shadow) { LEX_CSTRING db= {shadow->db, shadow->db_length }; thd->variables.option_bits = shadow->options; @@ -179,6 +355,7 @@ static void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow* shadow) thd->wsrep_exec_mode = shadow->wsrep_exec_mode; thd->net.vio = shadow->vio; thd->variables.tx_isolation = shadow->tx_isolation; + thd->set_row_count_func(shadow->row_count_func); thd->user_time = shadow->user_time; thd->reset_db(&db); @@ -195,9 +372,10 @@ static void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow* shadow) void wsrep_replay_transaction(THD *thd) { DBUG_ENTER("wsrep_replay_transaction"); + mysql_mutex_assert_owner(&thd->LOCK_wsrep_thd); /* checking if BF trx must be replayed */ - if (thd->wsrep_conflict_state== MUST_REPLAY) { - DBUG_ASSERT(wsrep_thd_trx_seqno(thd)); + if (thd->wsrep_conflict_state() == MUST_REPLAY) { + DBUG_ASSERT(wsrep_thd_trx_seqno(thd) > 0); if (thd->wsrep_exec_mode!= REPL_RECV) { if (thd->get_stmt_da()->is_sent()) { @@ -231,7 +409,7 @@ void wsrep_replay_transaction(THD *thd) thd->get_stmt_da()->reset_diagnostics_area(); - thd->wsrep_conflict_state= REPLAYING; + thd->set_wsrep_conflict_state(REPLAYING); mysql_mutex_unlock(&thd->LOCK_thd_data); thd->reset_for_next_command(); @@ -269,16 +447,22 @@ void wsrep_replay_transaction(THD *thd) (void *)thd); wsrep_return_from_bf_mode(thd, &shadow); - if (thd->wsrep_conflict_state!= REPLAYING) - WSREP_WARN("lost replaying mode: %d", thd->wsrep_conflict_state ); + + WSREP_DEBUG("replayed %lld, seqno %lld, rcode %d", + thd->thread_id, (long long)wsrep_thd_trx_seqno(thd), rcode); + DBUG_ASSERT(wsrep_thd_trx_seqno(thd) > 0); mysql_mutex_lock(&thd->LOCK_thd_data); + if (thd->wsrep_conflict_state() != REPLAYING) + WSREP_WARN("lost replaying mode: %d", thd->wsrep_conflict_state()); + switch (rcode) { case WSREP_OK: - thd->wsrep_conflict_state= NO_CONFLICT; - wsrep->post_commit(wsrep, &thd->wsrep_ws_handle); + thd->killed= NOT_KILLED; + thd->set_wsrep_conflict_state(NO_CONFLICT); + wsrep->release(wsrep, &thd->wsrep_ws_handle); WSREP_DEBUG("trx_replay successful for: %lld %lld", (longlong) thd->thread_id, (longlong) thd->real_id); if (thd->get_stmt_da()->is_sent()) @@ -317,19 +501,32 @@ void wsrep_replay_transaction(THD *thd) else { WSREP_DEBUG("replay failed, rolling back"); + my_error(ER_LOCK_DEADLOCK, MYF(0)); } - thd->wsrep_conflict_state= ABORTED; - wsrep->post_rollback(wsrep, &thd->wsrep_ws_handle); + WSREP_DEBUG("Setting thd to ABORTING, thd %lld conf %d", + thd->thread_id, thd->wsrep_conflict_state()); + if (thd->wsrep_conflict_state() != CERT_FAILURE) + thd->set_wsrep_conflict_state(ABORTING); + /* We returned out ouf order, trx is rolled back, + * no locks should remain. Need to do the total order part */ + DBUG_ASSERT(LOCAL_ROLLBACK != thd->wsrep_exec_mode); + thd->wsrep_exec_mode= LOCAL_ROLLBACK; + WSREP_DEBUG("replay_transaction(%lld) assigned LOCAL_ROLLBACK to " + "seqno %lld, conf %d", + thd->thread_id, (long long)wsrep_thd_trx_seqno(thd), + thd->wsrep_conflict_state()); + wsrep_post_rollback(thd); + break; default: WSREP_ERROR("trx_replay failed for: %d, schema: %s, query: %s", rcode, thd->get_db(), thd->query() ? thd->query() : "void"); + DBUG_ASSERT(0); /* we're now in inconsistent state, must abort */ /* http://bazaar.launchpad.net/~codership/codership-mysql/5.6/revision/3962#sql/wsrep_thd.cc */ mysql_mutex_unlock(&thd->LOCK_thd_data); - unireg_abort(1); break; } @@ -347,7 +544,8 @@ void wsrep_replay_transaction(THD *thd) DBUG_VOID_RETURN; } -static void wsrep_replication_process(THD *thd) +static void wsrep_replication_process(THD *thd, + void* arg __attribute__((unused))) { int rcode; DBUG_ENTER("wsrep_replication_process"); @@ -362,7 +560,8 @@ static void wsrep_replication_process(THD *thd) rcode = wsrep->recv(wsrep, (void *)thd); DBUG_PRINT("wsrep",("wsrep_repl returned: %d", rcode)); - WSREP_INFO("applier thread exiting (code:%d)", rcode); + WSREP_INFO("applier thread %lld exiting (code:%d)", + thd->thread_id, rcode); switch (rcode) { case WSREP_OK: @@ -414,13 +613,14 @@ static void wsrep_replication_process(THD *thd) DBUG_VOID_RETURN; } -static bool create_wsrep_THD(wsrep_thd_processor_fun processor) +static bool create_wsrep_THD(Wsrep_thd_args* args) { ulong old_wsrep_running_threads= wsrep_running_threads; pthread_t unused; mysql_mutex_lock(&LOCK_thread_count); + bool res= pthread_create(&unused, &connection_attrib, start_wsrep_THD, - (void*)processor); + args); /* if starting a thread on server startup, wait until the this thread's THD is fully initialized (otherwise a THD initialization code might @@ -449,21 +649,30 @@ void wsrep_create_appliers(long threads) } long wsrep_threads=0; - while (wsrep_threads++ < threads) { - if (create_wsrep_THD(wsrep_replication_process)) + + while (wsrep_threads++ < threads) + { + Wsrep_thd_args* args(new Wsrep_thd_args(wsrep_replication_process, 0)); + if (create_wsrep_THD(args)) + { WSREP_WARN("Can't create thread to manage wsrep replication"); + } } } -static void wsrep_rollback_process(THD *thd) +static void wsrep_rollback_process(THD *rollbacker, + void *arg __attribute__((unused))) { DBUG_ENTER("wsrep_rollback_process"); - mysql_mutex_lock(&LOCK_wsrep_rollback); - wsrep_aborting_thd= NULL; + THD* thd= NULL; + wsrep_rollback_queue= new Wsrep_thd_queue(rollbacker); - while (thd->killed == NOT_KILLED) { - thd_proc_info(thd, "WSREP aborter idle"); + thd_proc_info(rollbacker, "wsrep aborter idle"); + while ((thd= wsrep_rollback_queue->pop_front()) != NULL) + { +#ifdef OLD_MARIADB + thd_proc_info(thd, "wsrep aborter idle"); thd->mysys_var->current_mutex= &LOCK_wsrep_rollback; thd->mysys_var->current_cond= &COND_wsrep_rollback; @@ -496,52 +705,140 @@ static void wsrep_rollback_process(THD *thd) mysql_mutex_unlock(&LOCK_wsrep_rollback); mysql_mutex_lock(&aborting->LOCK_thd_data); - if (aborting->wsrep_conflict_state== ABORTED) + if (aborting->wsrep_conflict_state()== ABORTED) { WSREP_DEBUG("WSREP, thd already aborted: %llu state: %d", (long long)aborting->real_id, - aborting->wsrep_conflict_state); + aborting->wsrep_conflict_state()); mysql_mutex_unlock(&aborting->LOCK_thd_data); mysql_mutex_lock(&LOCK_wsrep_rollback); continue; } - aborting->wsrep_conflict_state= ABORTING; mysql_mutex_unlock(&aborting->LOCK_thd_data); set_current_thd(aborting); aborting->store_globals(); - mysql_mutex_lock(&aborting->LOCK_thd_data); - wsrep_client_rollback(aborting); - WSREP_DEBUG("WSREP rollbacker aborted thd: (%lld %lld)", - (longlong) aborting->thread_id, - (longlong) aborting->real_id); - mysql_mutex_unlock(&aborting->LOCK_thd_data); + if (wsrep_thd_is_SR(aborting)) + { + WSREP_DEBUG("WSREP rollbacker aborting SR thd: (%lld %llu)", + aborting->thread_id, (long long)aborting->real_id); + wsrep_abort_SR_THD(thd, aborting); + } + else + { + mysql_mutex_lock(&aborting->LOCK_wsrep_thd); + + /* prepare THD for rollback processing */ + aborting->reset_for_next_command(); + aborting->lex->sql_command= SQLCOM_ROLLBACK; - set_current_thd(thd); - thd->store_globals(); + wsrep_client_rollback(aborting, true); + mysql_mutex_unlock(&aborting->LOCK_wsrep_thd); + WSREP_DEBUG("WSREP rollbacker aborted thd: (%lld %llu)", + aborting->thread_id, (long long)aborting->real_id); + } mysql_mutex_lock(&LOCK_wsrep_rollback); } +#else + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state() == ABORTED) + { + WSREP_DEBUG("rollbacker thd already aborted: %llu state: %d", + (long long)thd->real_id, + thd->wsrep_conflict_state()); + + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + continue; + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + thd_proc_info(rollbacker, "wsrep aborter active"); + + thd->store_globals(); + if (wsrep_thd_is_SR(thd)) + { + WSREP_DEBUG("rollbacker aborting SR thd: (%lld %llu)", + thd->thread_id, (long long)thd->real_id); + wsrep_abort_SR_THD(rollbacker, thd); + } + else + { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + + /* prepare THD for rollback processing */ + thd->reset_for_next_command(); + thd->lex->sql_command= SQLCOM_ROLLBACK; + + wsrep_client_rollback(thd, true); + thd->reset_globals(); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + WSREP_DEBUG("rollbacker aborted thd: (%lld %llu)", + thd->thread_id, (long long)thd->real_id); + } + + thd_proc_info(rollbacker, "wsrep aborter idle"); +#endif } + + delete wsrep_rollback_queue; + wsrep_rollback_queue= NULL; - mysql_mutex_unlock(&LOCK_wsrep_rollback); sql_print_information("WSREP: rollbacker thread exiting"); + DBUG_ASSERT(rollbacker->killed != NOT_KILLED); DBUG_PRINT("wsrep",("wsrep rollbacker thread exiting")); DBUG_VOID_RETURN; } +static void wsrep_post_rollback_process(THD *post_rollbacker, + void *arg __attribute__((unused))) +{ + DBUG_ENTER("wsrep_post_rollback_process"); + THD* thd= NULL; + wsrep_post_rollback_queue= new Wsrep_thd_queue(post_rollbacker); + + while ((thd= wsrep_post_rollback_queue->pop_front()) != NULL) + { + thd->store_globals(); + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + DBUG_ASSERT(thd->wsrep_conflict_state() == ABORTING); + DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_ROLLBACK); + WSREP_DEBUG("post rollbacker calling post rollback for thd %lld, conf %s", + thd->thread_id, wsrep_thd_conflict_state_str(thd)); + + wsrep_post_rollback(thd); + DBUG_ASSERT(thd->wsrep_conflict_state() == ABORTED); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } + + delete wsrep_post_rollback_queue; + wsrep_post_rollback_queue= NULL; + + DBUG_ASSERT(post_rollbacker->killed != NOT_KILLED); + DBUG_PRINT("wsrep",("wsrep post rollbacker thread exiting")); + DBUG_VOID_RETURN; +} + void wsrep_create_rollbacker() { if (wsrep_provider && strcasecmp(wsrep_provider, "none")) { + Wsrep_thd_args* args= new Wsrep_thd_args(wsrep_rollback_process, 0); + /* create rollbacker */ - if (create_wsrep_THD(wsrep_rollback_process)) + if (create_wsrep_THD(args)) WSREP_WARN("Can't create thread to manage wsrep rollback"); - } + + /* create post_rollbacker */ + args= new Wsrep_thd_args(wsrep_post_rollback_process, 0); + if (create_wsrep_THD(args)) + WSREP_WARN("Can't create thread to manage wsrep post rollback"); + } } void wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe) @@ -560,7 +857,7 @@ enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd, my_bool sync) { if (sync) mysql_mutex_lock(&thd->LOCK_thd_data); - state = thd->wsrep_conflict_state; + state = thd->wsrep_conflict_state(); if (sync) mysql_mutex_unlock(&thd->LOCK_thd_data); } return state; @@ -576,11 +873,13 @@ my_bool wsrep_thd_is_wsrep(THD *thd) return status; } -my_bool wsrep_thd_is_BF(THD *thd, my_bool sync) +//my_bool wsrep_thd_is_BF(THD *thd, my_bool sync) +my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync) { my_bool status = FALSE; - if (thd) + if (thd_ptr) { + THD* thd = (THD*)thd_ptr; // THD can be BF only if provider exists if (wsrep_thd_is_wsrep(thd)) { @@ -596,6 +895,21 @@ my_bool wsrep_thd_is_BF(THD *thd, my_bool sync) return status; } +my_bool wsrep_thd_is_SR(void *thd_ptr) +{ + if (thd_ptr) + { + THD* thd = (THD*)thd_ptr; + return (thd->wsrep_SR_thd); + } + return false; +} + +my_bool wsrep_thd_skip_locking(void *thd) +{ + return thd != NULL && ((THD*)thd)->wsrep_skip_locking; +} + extern "C" my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync) { @@ -613,7 +927,6 @@ my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync) return status; } -extern "C" my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync) { bool status = FALSE; @@ -628,41 +941,66 @@ my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync) return status; } +/* + Start async rollback process + + Asserts thd->LOCK_wsrep_thd ownership + */ +void wsrep_fire_rollbacker(THD *thd) +{ + + mysql_mutex_assert_owner(&thd->LOCK_wsrep_thd); + DBUG_ASSERT(thd->wsrep_conflict_state() == MUST_ABORT); + + DBUG_PRINT("wsrep",("enqueuing trx abort for %llu", wsrep_thd_thread_id(thd))); + WSREP_DEBUG("enqueuing trx abort for (%llu)", wsrep_thd_thread_id(thd)); + + if (wsrep_rollback_queue->push_back(thd)) + { + WSREP_WARN("duplicate thd %llu for rollbacker", + wsrep_thd_thread_id(thd)); + } +} + + int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, my_bool signal) { THD *victim_thd = (THD *) victim_thd_ptr; THD *bf_thd = (THD *) bf_thd_ptr; DBUG_ENTER("wsrep_abort_thd"); + mysql_mutex_lock(&victim_thd->LOCK_wsrep_thd); if ( (WSREP(bf_thd) || ( (WSREP_ON || bf_thd->variables.wsrep_OSU_method == WSREP_OSU_RSU) && bf_thd->wsrep_exec_mode == TOTAL_ORDER) ) && - victim_thd) + victim_thd && + !victim_thd->wsrep_is_rolling_back()) { - if ((victim_thd->wsrep_conflict_state == MUST_ABORT) || - (victim_thd->wsrep_conflict_state == ABORTED) || - (victim_thd->wsrep_conflict_state == ABORTING)) + if (wsrep_thd_is_SR(victim_thd)) + { + victim_thd->set_wsrep_conflict_state(MUST_ABORT); + wsrep_fire_rollbacker(victim_thd); + { + WSREP_INFO("rollbacker fired for aborting SR transaction"); + } + } + else { - WSREP_DEBUG("wsrep_abort_thd called by %llu with victim %llu already " - "aborted. Ignoring.", - (bf_thd) ? (long long)bf_thd->real_id : 0, - (long long)victim_thd->real_id); - DBUG_RETURN(1); + WSREP_DEBUG("wsrep_abort_thd, by: %llu, victim: %llu", (bf_thd) ? + (long long)bf_thd->real_id : 0, (long long)victim_thd->real_id); + mysql_mutex_unlock(&victim_thd->LOCK_wsrep_thd); + ha_abort_transaction(bf_thd, victim_thd, signal); + mysql_mutex_lock(&victim_thd->LOCK_wsrep_thd); } - - WSREP_DEBUG("wsrep_abort_thd, by: %llu, victim: %llu", (bf_thd) ? - (long long)bf_thd->real_id : 0, (long long)victim_thd->real_id); - ha_abort_transaction(bf_thd, victim_thd, signal); } else { WSREP_DEBUG("wsrep_abort_thd not effective: %p %p", bf_thd, victim_thd); } - + mysql_mutex_unlock(&victim_thd->LOCK_wsrep_thd); DBUG_RETURN(1); } -extern "C" int wsrep_thd_in_locking_session(void *thd_ptr) { if (thd_ptr && ((THD *)thd_ptr)->in_lock_tables) { @@ -671,8 +1009,275 @@ int wsrep_thd_in_locking_session(void *thd_ptr) return 0; } +THD* wsrep_start_SR_THD(char *thread_stack) +{ + THD* thd; + if (!(thd= new THD(0))) + { + WSREP_ERROR("Could not create THD for Streaming Replication"); + goto err; + } + + thd->thread_stack= thread_stack; + + thd->real_id=pthread_self(); // Keep purify happy + mysql_mutex_lock(&LOCK_thread_count); + //add_global_thread(thd); + add_to_active_threads(thd); + + thd->thread_id= thd->variables.pseudo_thread_id= next_thread_id(); + (void)mysql_mutex_unlock(&LOCK_thread_count); + + thd->system_thread= SYSTEM_THREAD_SLAVE_SQL; + thd->security_ctx->skip_grants(); + thd->proc_info= 0; + thd->set_command(COM_SLEEP); + thd->set_time(); + thd->init_for_queries(); + + struct wsrep_thd_shadow shadow; + + wsrep_prepare_bf_thd(thd, &shadow); + + thd->wsrep_SR_thd = true; + WSREP_DEBUG("SR thread created, id: %lld thd: %p", thd->thread_id, thd); + err: + return thd; +} + +void wsrep_end_SR_THD(THD *thd) +{ + WSREP_DEBUG("Stopping Streaming Replication thd: %lld", thd->thread_id); + + close_thread_tables(thd); + mysql_mutex_lock(&LOCK_thread_count); + thd->unlink(); + mysql_mutex_unlock(&LOCK_thread_count); + + delete thd; + /* Remember that we don't have a THD */ + //my_pthread_setspecific_ptr(THR_THD, 0); + + my_thread_end(); +} + bool wsrep_thd_has_explicit_locks(THD *thd) { assert(thd); return thd->mdl_context.has_explicit_locks(); } + +static void +wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno) +{ + WSREP_ERROR("Trx %lld tries to abort slave trx %lld. This could be " + "caused by:\n\t" + "1) unsupported configuration options combination, please check documentation.\n\t" + "2) a bug in the code.\n\t" + "3) a database corruption.\n Node consistency compromized, " + "need to abort. Restart the node to resync with cluster.", + (long long)bf_seqno, (long long)victim_seqno); + abort(); +} + +static bool wsrep_abort_committing(THD *bf_thd, THD *victim_thd) +{ + mysql_mutex_assert_owner(&victim_thd->LOCK_wsrep_thd); + DBUG_ASSERT(victim_thd->wsrep_query_state() == QUERY_COMMITTING); + + wsrep_seqno_t const bf_seqno= bf_thd->wsrep_trx_meta.gtid.seqno; + wsrep_seqno_t victim_seqno= WSREP_SEQNO_UNDEFINED; + wsrep_status_t rcode= + wsrep->abort_certification(wsrep, bf_seqno, victim_thd->wsrep_trx_id(), + &victim_seqno); + bool must_abort= false; + switch (rcode) + { + case WSREP_OK: + /* The provider performed BF abort */ + WSREP_DEBUG("Provider performed BF abort"); + must_abort= true; + break; + case WSREP_NOT_ALLOWED: + /* The provider declined to do BF abort */ + WSREP_DEBUG("Provider declined to BF abort, victim is waiting to commit " + "with seqno %lld", (long long)victim_seqno ); + break; + case WSREP_TRX_MISSING: + /* The provider didn't yet know about the victim */ + break; + case WSREP_WARNING: + WSREP_DEBUG("abort_pre_commit warning: %lu", + victim_thd->wsrep_trx_id()); + break; + default: + WSREP_ERROR("abort_pre_commit bad exit: %d %lu", + rcode, victim_thd->wsrep_trx_id()); + abort(); + break; + } + + return must_abort; +} + + +/* + Function wsrep_bf_abort() should be called by the storage engine + whenever a high priority transaction tries to abort another + transaction. + + Whether the BF abort should happen depends on the vicim THD + state: + + Non-SR transaction: + * If the victim THD has been assigned a GTID and the GTID sequence + number is smaller than BF THD sequence number, the BF abort + request is declined and the caller should wait. + * If the victim THD has not been assigned a GTID or the sequence + number of the GTID is higher than the BF THD sequence number, + the victim must abort in order to allow the BF THD to proceed. + + SR transaction: + * If the victim THD has been assigned a GTID and the GTID sequence + number is smaller than BF THD sequence number *and* the victim + is committing the final fragment, the BF abort request is + declined and the caller should wait. + * Otherwise the victim transaction is aborted. + + Exactly how the BF abort takes place depends on victim THD + wsrep_query_state: + + * QUERY_COMMITTING and QUERY_COMMITTING_FRAGMENT: The victim + THD execution is between the provider pre_commit() hook + and the commit manager. The victim THD is signalled to abort + at server level and the caller should wait until the victim + rolls back. + * QUERY_EXEC: The victim THD is executing a query and the + caller should proceed to abort the transaction inside the + storage engine. + * QUERY_IDLE: The victim THD is idle and the responsibility + or rolling back the victim transaction is transferred to + rollbacker thread. The caller should wait until the rollbacker + thread finishes. + * QUERY_EXITING: The victim THD is in the process of closing the + connection. The caller should wait until the ongoing victim + transaction is rolled back. + + @return Return value true indicates that the caller should + proceed with internal storage engine BF abort sequence, + false indicates that the caller should wait for + the lock. +*/ +bool wsrep_bf_abort(void *bf_thd_ptr, void *victim_thd_ptr, bool signal) +{ + THD *bf_thd= (THD*)bf_thd_ptr; + THD *victim_thd= (THD*)victim_thd_ptr; + + mysql_mutex_assert_owner(&victim_thd->LOCK_wsrep_thd); + + WSREP_LOG_THD(bf_thd, "BF aborter before"); + WSREP_LOG_THD(victim_thd, "victim before"); + + wsrep_seqno_t const bf_seqno= bf_thd->wsrep_trx_meta.gtid.seqno; + wsrep_seqno_t victim_seqno= WSREP_SEQNO_UNDEFINED; + + if (victim_thd->wsrep_exec_mode == REPL_RECV) + { + wsrep_abort_slave_trx(bf_seqno, victim_seqno); /* Does not return */ + } + + DBUG_EXECUTE_IF("sync.wsrep_after_BF_victim_lock", + { + const char act[]= + "now " + "wait_for signal.wsrep_after_BF_victim_lock"; + DBUG_ASSERT(!debug_sync_set_action(bf_thd, + STRING_WITH_LEN(act))); + };); + + bool caller_must_bf_abort= false; + bool must_bf_abort= false; + bool must_fire_rollbacker= false; + switch (victim_thd->wsrep_query_state()) + { + case QUERY_COMMITTING: + /* + The query is committing either transaction or fragment, + the BF abort is attempted via provider. + */ + must_bf_abort= wsrep_abort_committing(bf_thd, victim_thd); + break; + case QUERY_ORDERED_COMMIT: + /* + Commit order has been grabbed, BF abort is not allowed. + */ + break; + case QUERY_EXEC: + /* + The victim THD is in execution phase and may be executing + a query inside storage engine. The control for further actions + will be returned to the caller. + */ + caller_must_bf_abort= true; + must_bf_abort= true; + break; + case QUERY_IDLE: + /* + The victim THD is idle. The victim must be marked as BF aborted + and the rollbacker thread must be signalled to do the actual rollback. + */ + must_bf_abort= true; + must_fire_rollbacker= true; + break; + case QUERY_EXITING: + /* + The victim connection is closing, the caller should wait for the + rollback. + */ + break; + } + + if (must_bf_abort) + { + switch (victim_thd->wsrep_conflict_state()) + { + case NO_CONFLICT: + wsrep_thd_set_conflict_state(victim_thd, MUST_ABORT); + break; + case MUST_ABORT: + wsrep_thd_awake(victim_thd, signal); + /* Fall through */ + case ABORTING: + case ABORTED: + case MUST_REPLAY: + case CERT_FAILURE: + /* + The victim is already in process of aborting the transaction, + the BF aborter should wait. + */ + must_bf_abort= false; + caller_must_bf_abort= false; + must_fire_rollbacker= false; + break; + default: + WSREP_WARN("BF abort for victim in state %s", + wsrep_thd_conflict_state_str(victim_thd)); + DBUG_ASSERT(0); /* Should not be here */ + must_bf_abort= false; + caller_must_bf_abort= false; + must_fire_rollbacker= false; + break; + } + } + + if (must_fire_rollbacker) + { + DBUG_ASSERT(must_bf_abort); + wsrep_fire_rollbacker(victim_thd); + } + + WSREP_LOG_THD(victim_thd, "victim after"); + + return caller_must_bf_abort; + +} diff --git a/sql/wsrep_thd.h b/sql/wsrep_thd.h index 5900668f3fb..996c1d0dddf 100644 --- a/sql/wsrep_thd.h +++ b/sql/wsrep_thd.h @@ -21,28 +21,194 @@ #ifdef WITH_WSREP #include "sql_class.h" +#include "wsrep_utils.h" +#include <deque> +class Wsrep_thd_queue +{ +public: + Wsrep_thd_queue(THD* t) : thd(t) + { + mysql_mutex_init(key_LOCK_wsrep_thd_queue, + &LOCK_wsrep_thd_queue, + MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_wsrep_thd_queue, &COND_wsrep_thd_queue, NULL); + } + ~Wsrep_thd_queue() + { + mysql_mutex_destroy(&LOCK_wsrep_thd_queue); + mysql_cond_destroy(&COND_wsrep_thd_queue); + } + bool push_back(THD* thd) + { + DBUG_ASSERT(thd); + wsp::auto_lock lock(&LOCK_wsrep_thd_queue); + std::deque<THD*>::iterator it = queue.begin(); + while (it != queue.end()) + { + if (*it == thd) + { + return true; + } + it++; + } + queue.push_back(thd); + mysql_cond_signal(&COND_wsrep_thd_queue); + return false; + } + THD* pop_front() + { + wsp::auto_lock lock(&LOCK_wsrep_thd_queue); + while (queue.empty()) + { + if (thd->killed != NOT_KILLED) + return NULL; + + thd->mysys_var->current_mutex= &LOCK_wsrep_thd_queue; + thd->mysys_var->current_cond= &COND_wsrep_thd_queue; + + mysql_cond_wait(&COND_wsrep_thd_queue, &LOCK_wsrep_thd_queue); + + thd->mysys_var->current_mutex= 0; + thd->mysys_var->current_cond= 0; + } + THD* ret= queue.front(); + queue.pop_front(); + return ret; + } +private: + THD* thd; + std::deque<THD*> queue; + mysql_mutex_t LOCK_wsrep_thd_queue; + mysql_cond_t COND_wsrep_thd_queue; +}; + +void wsrep_prepare_bf_thd(THD*, struct wsrep_thd_shadow*); +void wsrep_return_from_bf_mode(THD*, struct wsrep_thd_shadow*); int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, char *buff, enum enum_var_type scope); -void wsrep_client_rollback(THD *thd); +void wsrep_client_rollback(THD *thd, bool rollbacker = false); void wsrep_replay_transaction(THD *thd); void wsrep_create_appliers(long threads); void wsrep_create_rollbacker(); int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, my_bool signal); - +#ifndef OUT /* PA = Parallel Applying (on the slave side) */ extern void wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe); -extern my_bool wsrep_thd_is_BF(THD *thd, my_bool sync); +//extern my_bool wsrep_thd_is_BF(THD *thd, my_bool sync); +extern my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync); extern my_bool wsrep_thd_is_wsrep(void *thd_ptr); -enum wsrep_conflict_state wsrep_thd_conflict_state(void *thd_ptr, my_bool sync); +//enum wsrep_conflict_state wsrep_thd_conflict_state(void *thd_ptr, my_bool sync); +//extern int wsrep_thd_conflict_state(void *thd_ptr, my_bool sync); +//extern char* wsrep_thd_query(void *thd_ptr); extern "C" my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync); extern "C" my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync); -extern "C" int wsrep_thd_in_locking_session(void *thd_ptr); +int wsrep_thd_in_locking_session(void *thd_ptr); +THD* wsrep_start_SR_THD(char *thread_stack); +void wsrep_end_SR_THD(THD* thd); +extern my_bool wsrep_thd_is_SR(void *thd_ptr); +extern my_bool wsrep_thd_skip_locking(void *thd); +#endif + +/** + Helper functions to override error status + + In many contexts it is desirable to mask the original error status + set for THD or it is necessary to change OK status to error. + This function implements the common logic for the most + of the cases. + + Rules: + * If the diagnostics are has OK or EOF status, override it unconditionally + * If the error is either ER_ERROR_DURING_COMMIT or ER_LOCK_DEADLOCK + it is usually the correct error status to be returned to client, + so don't override those by default + */ + +static inline void wsrep_override_error(THD *thd, uint error) +{ + Diagnostics_area *da= thd->get_stmt_da(); + if (da->is_ok() || + da->is_eof() || + !da->is_set() || + (da->is_error() && + da->sql_errno() != error && + da->sql_errno() != ER_ERROR_DURING_COMMIT && + da->sql_errno() != ER_LOCK_DEADLOCK)) + { + da->reset_diagnostics_area(); + my_error(error, MYF(0)); + } +} + +/** + Override error with additional wsrep status. + */ +static inline void wsrep_override_error(THD *thd, uint error, + wsrep_status_t status) +{ + Diagnostics_area *da= thd->get_stmt_da(); + if (da->is_ok() || + !da->is_set() || + (da->is_error() && + da->sql_errno() != error && + da->sql_errno() != ER_ERROR_DURING_COMMIT && + da->sql_errno() != ER_LOCK_DEADLOCK)) + { + da->reset_diagnostics_area(); + my_error(error, MYF(0), status); + } +} + + +/** + Helper function to log THD wsrep context. + + @param thd Pointer to THD + @param message Optional message + @param function Function where the call was made from + */ +static inline void wsrep_log_thd(THD *thd, + const char *message, + const char *function) +{ + WSREP_DEBUG("%s %s\n" + " thd: %llu thd_ptr: %p exec_mode: %s query_state: %s conflict_state: %s\n" + " next_trx_id: %lld trx_id: %lld seqno: %lld\n" + " is_streaming: %d fragments: %zu\n" + " sql_errno: %u message: %s\n" +#define WSREP_THD_LOG_QUERIES +#ifdef WSREP_THD_LOG_QUERIES + " command: %d query: %.72s" +#endif /* WSREP_OBSERVER_LOG_QUERIES */ + , + function, + message ? message : "", + thd->thread_id, + thd, + wsrep_thd_exec_mode_str(thd), + wsrep_thd_query_state_str(thd), + wsrep_thd_conflict_state_str(thd), + (long long)thd->wsrep_next_trx_id(), + (long long)thd->wsrep_trx_id(), + (long long)thd->wsrep_trx_meta.gtid.seqno, + thd->wsrep_is_streaming(), + thd->wsrep_SR_fragments.size(), + (thd->get_stmt_da()->is_error() ? thd->get_stmt_da()->sql_errno() : 0), + (thd->get_stmt_da()->is_error() ? thd->get_stmt_da()->message() : "") +#ifdef WSREP_THD_LOG_QUERIES + , thd->lex->sql_command, + WSREP_QUERY(thd) +#endif /* WSREP_OBSERVER_LOG_QUERIES */ + ); +} + +#define WSREP_LOG_THD(thd_, message_) wsrep_log_thd(thd_, message_, __FUNCTION__) #else /* WITH_WSREP */ diff --git a/sql/wsrep_thd_pool.cc b/sql/wsrep_thd_pool.cc new file mode 100644 index 00000000000..d65b5bde185 --- /dev/null +++ b/sql/wsrep_thd_pool.cc @@ -0,0 +1,122 @@ +/* Copyright (C) 2015 Codership Oy <info@codership.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + + +#include <my_global.h> +#include "my_pthread.h" +#include "wsrep_mysqld.h" +#include "wsrep_thd_pool.h" +#include "wsrep_utils.h" +#include "sql_class.h" +//#include "global_threads.h" + +#include <list> + +static THD* wsrep_thd_pool_new_thd() +{ + THD *thd = new THD(next_thread_id()); + thd->thread_stack= (char*) &thd; + thd->security_ctx->skip_grants(); + thd->system_thread= SYSTEM_THREAD_GENERIC; + + mysql_mutex_lock(&LOCK_thread_count); + + thd->real_id=pthread_self(); // Keep purify happy + + WSREP_DEBUG("Wsrep_thd_pool: creating system thread: %lld", + (long long)thd->thread_id); + thd->prior_thr_create_utime= thd->start_utime= thd->thr_create_utime; + (void) mysql_mutex_unlock(&LOCK_thread_count); + + thd->variables.wsrep_on = 0; + thd->variables.sql_log_bin = 0; + thd->variables.option_bits &= ~OPTION_BIN_LOG; + thd->variables.tx_isolation = ISO_READ_COMMITTED; + + thd->wsrep_exec_mode = REPL_RECV; + // thd->wsrep_exec_mode = LOCAL_STATE; + + return thd; +} + +Wsrep_thd_pool::Wsrep_thd_pool(size_t threads) + : + threads_(threads), + pool_() +{ + WSREP_DEBUG("Wsrep_thd_pool constructor"); + wsp::auto_lock lock(&LOCK_wsrep_thd_pool); + pool_.reserve(threads); + for (size_t i= 0; i < threads; ++i) + { + pool_.push_back(wsrep_thd_pool_new_thd()); + } +} + +Wsrep_thd_pool::~Wsrep_thd_pool() +{ + wsp::auto_lock lock(&LOCK_wsrep_thd_pool); + while (!pool_.empty()) + { + THD *thd = pool_.back(); + WSREP_DEBUG("Wsrep_thd_pool: closing thread %lld", + (long long)thd->thread_id); + + delete thd; + + pool_.pop_back(); + } +} + +THD* Wsrep_thd_pool::get_thd(THD* thd) +{ + wsp::auto_lock lock(&LOCK_wsrep_thd_pool); + THD *ret= NULL; + if (pool_.empty()) + { + ret= wsrep_thd_pool_new_thd(); + } + else + { + ret= pool_.back(); + pool_.pop_back(); + } + if (thd) + { + ret->thread_stack = thd->thread_stack; + } + else + { + ret->thread_stack= (char*) &ret; + } + ret->store_globals(); + return ret; +} + +void Wsrep_thd_pool::release_thd(THD* thd) +{ + DBUG_ASSERT(!thd->mdl_context.has_locks()); + DBUG_ASSERT(!thd->open_tables); + DBUG_ASSERT(thd->transaction.stmt.is_empty()); + wsp::auto_lock lock(&LOCK_wsrep_thd_pool); + if (pool_.size() < threads_) + { + pool_.push_back(thd); + } + else + { + delete thd; + } +} diff --git a/sql/wsrep_thd_pool.h b/sql/wsrep_thd_pool.h new file mode 100644 index 00000000000..af335ac3b87 --- /dev/null +++ b/sql/wsrep_thd_pool.h @@ -0,0 +1,37 @@ +/* Copyright (C) 2015 Codership Oy <info@codership.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + + +#ifndef WSREP_THD_POOL_H +#define WSREP_THD_POOL_H + +#include <cstddef> +#include <vector> + +class THD; + +class Wsrep_thd_pool +{ +public: + Wsrep_thd_pool(size_t threads = 10); + ~Wsrep_thd_pool(); + THD* get_thd(THD*); + void release_thd(THD*); +private: + size_t threads_; + std::vector<THD*> pool_; +}; + +#endif /* !WSREP_THD_POOL_H */ diff --git a/sql/wsrep_trans_observer.cc b/sql/wsrep_trans_observer.cc new file mode 100644 index 00000000000..9a914ea37b7 --- /dev/null +++ b/sql/wsrep_trans_observer.cc @@ -0,0 +1,1663 @@ +/* Copyright 2016 Codership Oy <http://www.codership.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +/* + Implementation of wsrep transaction observer hooks. + + * wsrep_after_row(): called after each row write/update/delete, will run + SR step + * wsrep_before_prepare(): SR table cleanup + * wsrep_after_prepare(): will run wsrep_certify() which replicates + and certifies transaction for transactions which have registered + binlog hton + * wsrep_before_commit(): run wsrep_certify() for autocommit + DML when binlog_format = STATEMENT and grab commit time + critical via section wsrep->commit_order_enter() + * wsrep_ordered_commit(): release commit time critical section + via wsrep->commit_order_leave() + * wsrep_after_commit(): release rest of the trx resources from + provider + * wsrep_before_rollback(): on SR rollback construct SR_trx_info + and send rollback event before actual rollback happens. Set + wsrep_exec_mode to LOCAL_ROLLBACK + * wsrep_after_rollback(): in case of statement rollback check if + it is safe for SR and if not, trigger full transaction rollback + * wsrep_after_command(): + * run wsrep_SR_step() + * perform post rollback operations for thds which have + wsrep_exec_mode LOCAL_ROLLBACK + * perform wsrep_client_rollback() for thds with wsrep_conflict_state + MUST_ABORT or CERT_FAILURE + * run wsrep_client_rollback() for thd which has seqno assigned + * cleanup transaction after rollback + * do rollback process for threads which have BF aborted or have + failed certification but have not rolled back yet. + * replay transactions which need to be replayed + + + Note: The rollback processing has been postponed to after_command hook + because sometimes the rollback process needs to be done for threads + which have valid wsrep seqno and rollback for such a threads should + be done after all tables are closed in order to avoid deadlocks. + Although wsrep rollback steps would be possible to do earlier in + after_rollback hook, this approach was chosen for simplicity. +*/ + + +#include "wsrep_trans_observer.h" +#include "wsrep_mysqld.h" +#include "wsrep_xid.h" +#include "wsrep_sr.h" +#include "wsrep_thd.h" + +#include "replication.h" +#include "transaction.h" +#include "sql_base.h" /* close_thread_tables() */ +#include "sql_class.h" /* THD */ +#include "sql_parse.h" /* stmt_causes_implicit_commit() */ +#include "rpl_filter.h" /* Rpl_filter */ +#include "log.h" +#include "debug_sync.h" /* DEBUG_SYNC */ + +#include <map> + +extern class SR_storage *wsrep_SR_store; +extern Rpl_filter* binlog_filter; + + +static void wsrep_wait_for_replayers(THD *thd) +{ + mysql_mutex_lock(&LOCK_wsrep_replaying); + int replay_round= 0; + while (wsrep_replaying > 0 && + thd->wsrep_conflict_state() == NO_CONFLICT && + thd->killed == NOT_KILLED && + !shutdown_in_progress) + { + + mysql_mutex_unlock(&LOCK_wsrep_replaying); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + mysql_mutex_lock(&thd->mysys_var->mutex); + thd_proc_info(thd, "wsrep waiting on replaying"); + thd->mysys_var->current_mutex= &LOCK_wsrep_replaying; + thd->mysys_var->current_cond= &COND_wsrep_replaying; + mysql_mutex_unlock(&thd->mysys_var->mutex); + + mysql_mutex_lock(&LOCK_wsrep_replaying); + // Using timedwait is a hack to avoid deadlock in case if BF victim + // misses the signal. + struct timespec wtime; + clock_gettime(CLOCK_REALTIME, &wtime); + long prev_nsec = wtime.tv_nsec; + wtime.tv_nsec = (wtime.tv_nsec + 1000000) % 1000000000; + // If nsecs rolled over, increment seconds. + wtime.tv_sec += (wtime.tv_nsec < prev_nsec ? 1 : 0); + mysql_cond_timedwait(&COND_wsrep_replaying, &LOCK_wsrep_replaying, + &wtime); + + if (replay_round++ % 100000 == 0) + WSREP_DEBUG("commit waiting for replaying: replayers %d, thd: (%lld) " + "conflict: %d (round: %d)", + wsrep_replaying, thd->thread_id, + thd->wsrep_conflict_state_unsafe(), replay_round); + + mysql_mutex_unlock(&LOCK_wsrep_replaying); + + mysql_mutex_lock(&thd->mysys_var->mutex); + thd->mysys_var->current_mutex= 0; + thd->mysys_var->current_cond= 0; + mysql_mutex_unlock(&thd->mysys_var->mutex); + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + mysql_mutex_lock(&LOCK_wsrep_replaying); + } + mysql_mutex_unlock(&LOCK_wsrep_replaying); +} + +static int wsrep_prepare_data_for_replication(THD *thd) +{ + DBUG_ENTER("wsrep_prepare_data_for_replication"); + size_t data_len= 0; + IO_CACHE* cache= wsrep_get_trans_cache(thd); + + if (cache) + { + thd->binlog_flush_pending_rows_event(true); + enum wsrep_trx_status rcode= wsrep_write_cache(wsrep, thd, cache, &data_len); + if (rcode != WSREP_TRX_OK) + { + WSREP_ERROR("rbr write fail, data_len:: %zu", + data_len); + wsrep_override_error(thd, ER_ERROR_DURING_COMMIT, + wsrep_trx_status_to_wsrep_status(rcode)); + DBUG_RETURN(1); + } + } + + if (data_len == 0) + { + if (thd->get_stmt_da()->is_ok() && + thd->get_stmt_da()->affected_rows() > 0 && + !binlog_filter->is_on()) + { + WSREP_DEBUG("empty rbr buffer, query: %s, " + "affected rows: %llu, " + "changed tables: %d, " + "sql_log_bin: %d, " + "wsrep status (%d %d %d)", + WSREP_QUERY(thd), + thd->get_stmt_da()->affected_rows(), + stmt_has_updated_trans_table(thd), + thd->variables.sql_log_bin, + thd->wsrep_exec_mode, thd->wsrep_query_state_unsafe(), + thd->wsrep_conflict_state_unsafe()); + } + else + { + WSREP_DEBUG("empty rbr buffer, query: %s", WSREP_QUERY(thd)); + } + + if (!thd->wsrep_is_streaming()) + { + WSREP_ERROR("I/O error reading from thd's binlog iocache: " + "errno=%d, io cache code=%d", my_errno, cache->error); + wsrep_override_error(thd, ER_ERROR_DURING_COMMIT); + DBUG_RETURN(1); + } + } + DBUG_RETURN(0); +} + +/* + Run wsrep pre_commit phase + + Asserts thd->LOCK_wsrep_thd ownership + */ +static wsrep_trx_status wsrep_certify(THD *thd) +{ + mysql_mutex_assert_owner(&thd->LOCK_wsrep_thd); + DBUG_ENTER("wsrep_certify"); + DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT); + DBUG_ASSERT(thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID); + + /* + We must not proceed for certify() if there are threads + replaying transactions. This is because replaying thread + may have released some locks which this thread then acquired. + + Now if the replaying ends before write set gets replicated, + the replayed write set may fall out of this write sets + certification range, so the conflict won't be detected. + This will lead to applying error later on. + + Conflict state must be checked out once more after waiting + for replayers to detect if replaying transaction (or other) + has BF aborted this. + */ + wsrep_wait_for_replayers(thd); + if (thd->wsrep_conflict_state() == MUST_ABORT) + { + // Transaction was BF aborted + wsrep_override_error(thd, ER_LOCK_DEADLOCK); + DBUG_RETURN(WSREP_TRX_ERROR); + } + + thd->set_wsrep_query_state(QUERY_COMMITTING); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + DEBUG_SYNC(thd, "wsrep_before_replication"); + + if (wsrep_prepare_data_for_replication(thd)) + { + /* Error will be set in function to prepare data */ + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_EXEC); + DBUG_RETURN(WSREP_TRX_ERROR); + } + + if (thd->killed != NOT_KILLED) + { + WSREP_INFO("thd %lld killed with signal %d, skipping replication", + thd->thread_id, thd->killed); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + wsrep_override_error(thd, ER_LOCK_DEADLOCK); + thd->set_wsrep_query_state(QUERY_EXEC); + DBUG_RETURN(WSREP_TRX_ERROR); + } + + DBUG_ASSERT(thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID); + if (WSREP_UNDEFINED_TRX_ID == thd->wsrep_trx_id()) + { + WSREP_WARN("SQL statement was ineffective, THD: %lld\n" + "schema: %s \n" + "QUERY: %s\n" + " => Skipping replication", + thd->thread_id, + (thd->db.str ? thd->db.str : "(null)"), + WSREP_QUERY(thd)); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + wsrep_override_error(thd, ER_ERROR_DURING_COMMIT); + thd->set_wsrep_query_state(QUERY_EXEC); + DBUG_RETURN(WSREP_TRX_ERROR); + } + + uint32_t flags= WSREP_FLAG_TRX_END; + if (!thd->wsrep_PA_safe || thd->wsrep_is_streaming()) + { + flags |= WSREP_FLAG_PA_UNSAFE; + } + + if (thd->wsrep_is_streaming()) + { + if (!wsrep_append_SR_keys(thd)) + { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + wsrep_override_error(thd, ER_ERROR_DURING_COMMIT); + thd->set_wsrep_query_state(QUERY_EXEC); + DBUG_RETURN(WSREP_TRX_ERROR); + } + } + + wsrep_status_t rcode= wsrep->certify(wsrep, + (wsrep_conn_id_t) thd->thread_id, + &thd->wsrep_ws_handle, + flags, + &thd->wsrep_trx_meta); + + WSREP_DEBUG("Trx certify(%lu): rcode %d, seqno %lld, trx %ld, " + "flags %u, conf %d, SQL: %s", + thd->thread_id, rcode,(long long)thd->wsrep_trx_meta.gtid.seqno, + thd->wsrep_trx_meta.stid.trx, flags, thd->wsrep_conflict_state_unsafe(), + thd->query()); + + DBUG_ASSERT((thd->wsrep_trx_meta.depends_on >= 0 && + thd->wsrep_trx_meta.depends_on < + thd->wsrep_trx_meta.gtid.seqno) || + WSREP_OK != rcode); + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + + DEBUG_SYNC(thd, "wsrep_after_replication"); + + if (WSREP_OK == rcode) + { + DBUG_ASSERT(wsrep_thd_trx_seqno(thd) > 0); + + if (thd->wsrep_conflict_state() == MUST_ABORT) + { + rcode= WSREP_BF_ABORT; + WSREP_DEBUG("Not calling commit_order_enter() due to conflict state" + " == MUST_ABORT thd: %lu, seqno: %lld", + thd->thread_id, (long long)wsrep_thd_trx_seqno(thd)); + } + } + + wsrep_trx_status ret= WSREP_TRX_ERROR; + + switch (rcode) + { + case WSREP_TRX_MISSING: + WSREP_WARN("Transaction missing in provider thd: %lld schema: %s SQL: %s", + thd->thread_id, (thd->db.str ? thd->db.str : "(null)"), + WSREP_QUERY(thd)); + my_error(ER_ERROR_DURING_COMMIT, MYF(0), WSREP_TRX_MISSING); + break; + case WSREP_BF_ABORT: + DBUG_ASSERT(wsrep_thd_trx_seqno(thd) > 0); + thd->set_wsrep_conflict_state(MUST_REPLAY); + mysql_mutex_lock(&LOCK_wsrep_replaying); + ++wsrep_replaying; + mysql_mutex_unlock(&LOCK_wsrep_replaying); + break; + case WSREP_OK: + /* + Ignore BF abort from storage engine in commit phase. + This however requires that the storage engine BF abort + respects QUERY_COMMITTING query state. + + TODO: Consider removing this and respecting BF abort. + Also adjust allowed state transitions in + THD::set_wsrep_conflict_state(). + + NOTE: If we have rcode WSREP_OK here it means that transaction + entered commit critical section in wsrep->commit_order_enter() + call. It is a bug in a provider/BF abort code if it allowed + BF abort after that. + */ + DBUG_ASSERT(wsrep_thd_trx_seqno(thd) > 0); + DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT); + + if (thd->wsrep_conflict_state() == MUST_ABORT) + { + thd->killed= NOT_KILLED; + WSREP_WARN("Ignoring MUST_ABORT state"); + thd->set_wsrep_conflict_state(NO_CONFLICT); + } + + thd->wsrep_exec_mode= LOCAL_COMMIT; + DBUG_PRINT("wsrep", ("replicating commit success")); + DBUG_EXECUTE_IF("crash_last_fragment_commit_success", + DBUG_SUICIDE();); + ret= WSREP_TRX_OK; + break; + case WSREP_TRX_FAIL: + if (thd->wsrep_conflict_state() == NO_CONFLICT) + { + thd->set_wsrep_conflict_state(CERT_FAILURE); + WSREP_LOG_CONFLICT(NULL, thd, FALSE); + } + else + { + DBUG_ASSERT(thd->wsrep_conflict_state() == MUST_ABORT); + } + my_error(ER_LOCK_DEADLOCK, MYF(0), WSREP_TRX_FAIL); + ret= WSREP_TRX_CERT_FAIL; + break; + case WSREP_SIZE_EXCEEDED: + WSREP_ERROR("wsrep_certify(%lu): transaction size exceeded", + thd->thread_id); + my_error(ER_ERROR_DURING_COMMIT, MYF(0), WSREP_SIZE_EXCEEDED); + ret= WSREP_TRX_SIZE_EXCEEDED; + break; + case WSREP_CONN_FAIL: + WSREP_DEBUG("wsrep_certify(%lu): replication aborted", + thd->thread_id); + my_error(ER_LOCK_DEADLOCK, MYF(0), WSREP_CONN_FAIL); + break; + case WSREP_WARNING: + WSREP_WARN("provider returned warning"); + my_error(ER_ERROR_DURING_COMMIT, MYF(0), WSREP_WARNING); + break; + case WSREP_NODE_FAIL: + WSREP_ERROR("replication aborted"); + my_error(ER_ERROR_DURING_COMMIT, MYF(0), WSREP_NODE_FAIL); + break; + case WSREP_NOT_IMPLEMENTED: + WSREP_ERROR("certify() or commit_order_enter() not implemented"); + my_error(ER_ERROR_DURING_COMMIT, MYF(0), WSREP_NOT_IMPLEMENTED); + break; + default: + WSREP_ERROR("wsrep_certify(%lu): unknown provider failure", + thd->thread_id); + my_error(ER_ERROR_DURING_COMMIT, MYF(0), rcode); + break; + } + + /* + In case of success we keep the QUERY_COMMITTING + */ + if (rcode != WSREP_OK) + { + thd->set_wsrep_query_state(QUERY_EXEC); + } + + DBUG_RETURN(ret); +} + +static wsrep_trx_status wsrep_replicate_fragment(THD *thd) +{ + mysql_mutex_assert_owner(&thd->LOCK_wsrep_thd); + DBUG_ENTER("wsrep_replicate_fragment"); + DBUG_ASSERT(thd->wsrep_exec_mode != REPL_RECV && + thd->wsrep_exec_mode != TOTAL_ORDER); + DBUG_ASSERT(thd->wsrep_SR_rollback_replicated_for_trx != + thd->wsrep_trx_id()); + DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT); + + wsrep_wait_for_replayers(thd); + if (thd->wsrep_conflict_state() == MUST_ABORT) + { + // Transaction was BF aborted + wsrep_override_error(thd, ER_LOCK_DEADLOCK); + DBUG_RETURN(WSREP_TRX_ERROR); + } + + thd->set_wsrep_query_state(QUERY_COMMITTING); + + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + bool reset_trx_meta= false; + IO_CACHE *cache= wsrep_get_trans_cache(thd); + size_t data_len= 0; + uint32_t flags= (thd->wsrep_PA_safe ? 0 : WSREP_FLAG_PA_UNSAFE); + if (thd->wsrep_fragments_sent == 0) + { + flags |= WSREP_FLAG_TRX_START; + } + + /* + thd->wsrep_fragments_sent must be incremented before wsrep_write_cache + to get thd->wsrep_rbr_buf populated. This also needs to be decremented + whenever error is returned from this function. + */ + ++thd->wsrep_fragments_sent; + if (cache) + { + enum wsrep_trx_status rcode; + if ((rcode = wsrep_write_cache(wsrep, thd, cache, &data_len)) != WSREP_TRX_OK) + { + WSREP_ERROR("SR rbr write fail, data_len: %zu ret: %d", + data_len, rcode); + --thd->wsrep_fragments_sent; + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_EXEC); + DBUG_RETURN(rcode); + } + } + +#if 0 + WSREP_INFO("wsrep_replicate_fragment: base: %lu bytes: %u data_len %zu fragments_sent: %lu", + wsrep_get_fragment_base(thd), + wsrep_get_trans_cache_position(thd), + data_len, + thd->wsrep_fragments_sent); +#endif + + if (data_len == 0) + { + if (thd->get_stmt_da()->is_ok() && + thd->get_stmt_da()->affected_rows() > 0 && + !binlog_filter->is_on()) + { + WSREP_WARN("empty rbr buffer, query: %s, " + "affected rows: %llu, " + "changed tables: %d, " + "sql_log_bin: %d, " + "wsrep status (%d %d %d)", + thd->query(), thd->get_stmt_da()->affected_rows(), + stmt_has_updated_trans_table(thd), + thd->variables.sql_log_bin, + thd->wsrep_exec_mode, thd->wsrep_query_state(), + thd->wsrep_conflict_state_unsafe()); + } + else + { + WSREP_WARN("empty rbr buffer, query: %s", thd->query()); + } + --thd->wsrep_fragments_sent; + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_EXEC); + DBUG_RETURN(WSREP_TRX_ERROR); + } + + DBUG_ASSERT(thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID); + if (WSREP_UNDEFINED_TRX_ID == thd->wsrep_trx_id()) + { + WSREP_WARN("SQL statement was ineffective, THD: %lld, buf: %zu\n" + "QUERY: %s\n" + " => Skipping fragment replication", + thd->thread_id, data_len, thd->query()); + --thd->wsrep_fragments_sent; + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_EXEC); + DBUG_RETURN(WSREP_TRX_ERROR); + } + + THD *SR_thd= NULL; + if (wsrep_SR_store) + { + SR_thd= wsrep_SR_store->append_frag(thd, flags, thd->wsrep_rbr_buf, + data_len); + if (!SR_thd) + { + my_error(ER_BINLOG_ROW_LOGGING_FAILED, MYF(0)); + --thd->wsrep_fragments_sent; + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_EXEC); + DBUG_RETURN(WSREP_TRX_ERROR); + } + } + + my_free(thd->wsrep_rbr_buf); + thd->wsrep_rbr_buf= NULL; + + DBUG_EXECUTE_IF("crash_replicate_fragment_before_certify", + DBUG_SUICIDE();); + + wsrep_status_t rcode= wsrep->certify(wsrep, + (wsrep_conn_id_t)thd->thread_id, + &thd->wsrep_ws_handle, + flags, + &thd->wsrep_trx_meta); + + WSREP_DEBUG("Fragment certify(%lu): rcode %d, seqno %lld, trx %ld, " + "flags %u, conf %d, SQL: %s", + thd->thread_id, rcode,(long long)thd->wsrep_trx_meta.gtid.seqno, + thd->wsrep_trx_meta.stid.trx, flags, + thd->wsrep_conflict_state_unsafe(), + thd->query()); + DBUG_EXECUTE_IF("crash_replicate_fragment_after_certify", + DBUG_SUICIDE();); + + bool frag_updated= false; + if (WSREP_OK == rcode) + { + DBUG_ASSERT(thd->wsrep_trx_has_seqno()); + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + my_bool const must_abort= (thd->wsrep_conflict_state() == MUST_ABORT); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + if (must_abort) + { + rcode= WSREP_BF_ABORT; + } + else + { + rcode= wsrep->commit_order_enter(wsrep, &thd->wsrep_ws_handle, + &thd->wsrep_trx_meta); + if (rcode == WSREP_OK) + { + wsrep_xid_init(&SR_thd->wsrep_xid, thd->wsrep_trx_meta.gtid.uuid, + thd->wsrep_trx_meta.gtid.seqno); + wsrep_SR_store->update_frag_seqno(SR_thd, thd); + frag_updated= true; + rcode= wsrep->commit_order_leave(wsrep, &thd->wsrep_ws_handle, + &thd->wsrep_trx_meta, NULL); + if (rcode != WSREP_OK && rcode != WSREP_BF_ABORT) + { + WSREP_ERROR("wsrep_replicate_fragment(%lu): seqno %lld, trx %ld " + "Failed to leave commit order %d", + thd->thread_id, + (long long)thd->wsrep_trx_meta.gtid.seqno, + thd->wsrep_trx_meta.stid.trx, + rcode); + } + if (rcode == WSREP_OK) + { + rcode= wsrep->release(wsrep, &thd->wsrep_ws_handle); + if (rcode != WSREP_OK) + { + WSREP_ERROR("wsrep_replicate_fragment(%lu): seqno %lld, trx %ld " + "Failed to release ws handle %d", + thd->thread_id, + (long long)thd->wsrep_trx_meta.gtid.seqno, + thd->wsrep_trx_meta.stid.trx, + rcode); + } + } + reset_trx_meta= true; + } + else + { + DBUG_ASSERT(rcode == WSREP_BF_ABORT || rcode == WSREP_TRX_FAIL); + } + } + } + + if (!frag_updated) + { + wsrep_SR_store->release_SR_thd(SR_thd); + SR_thd= NULL; + thd->store_globals(); + } + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + /* + If the SR transaction was BF aborted at this stage + we abort whole transaction. + */ + if (thd->wsrep_conflict_state() == MUST_ABORT) + { + rcode= WSREP_BF_ABORT; + } + + wsrep_trx_status ret; + + switch (rcode) + { + case WSREP_OK: + DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT); + DBUG_PRINT("wsrep", ("replicating commit success")); + if (thd->killed != NOT_KILLED) + { + WSREP_DEBUG("thd %lld killed with signal %d, during fragment replication", + thd->thread_id, thd->killed); + } + DBUG_EXECUTE_IF("crash_replicate_fragment_success", + DBUG_SUICIDE();); + ret= WSREP_TRX_OK; + break; + case WSREP_BF_ABORT: + if (thd->wsrep_conflict_state() != MUST_ABORT) + { + thd->set_wsrep_conflict_state(MUST_ABORT); + } + wsrep_override_error(thd, ER_LOCK_DEADLOCK, WSREP_TRX_FAIL); + ret= WSREP_TRX_ERROR; + break; + case WSREP_TRX_FAIL: + thd->set_wsrep_conflict_state(CERT_FAILURE); + WSREP_LOG_CONFLICT(NULL, thd, FALSE); + wsrep_override_error(thd, ER_LOCK_DEADLOCK, WSREP_TRX_FAIL); + ret= WSREP_TRX_CERT_FAIL; + break; + case WSREP_SIZE_EXCEEDED: + thd->set_wsrep_conflict_state(MUST_ABORT); + ret= WSREP_TRX_SIZE_EXCEEDED; + break; + case WSREP_CONN_FAIL: + thd->set_wsrep_conflict_state(MUST_ABORT); + my_error(ER_LOCK_DEADLOCK, MYF(0)); + ret= WSREP_TRX_ERROR; + break; + default: + thd->set_wsrep_conflict_state(MUST_ABORT); + ret= WSREP_TRX_ERROR; + break; + } + + thd->set_wsrep_query_state(QUERY_EXEC); + + if (SR_thd && wsrep_thd_trx_seqno(thd) == WSREP_SEQNO_UNDEFINED) + { + --thd->wsrep_fragments_sent; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + wsrep_SR_store->release_SR_thd(SR_thd); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->store_globals(); + } + + /* + Reset trx meta if pre_commit certify() (regardless of conflict state), + new seqno will be used for next fragment. + In case of failure GTID may be required in rollback process. + */ + if (reset_trx_meta) + { + WSREP_DEBUG("Reset trx meta for %lu", thd->thread_id); + thd->wsrep_trx_meta.gtid= WSREP_GTID_UNDEFINED; + thd->wsrep_trx_meta.depends_on= WSREP_SEQNO_UNDEFINED; + } + + DBUG_RETURN(ret); +} + +static int wsrep_SR_step(THD *thd, uint unit) +{ + mysql_mutex_assert_owner(&thd->LOCK_wsrep_thd); + DBUG_ENTER("wsrep_SR_step"); + if (!wsrep_may_produce_SR_step(thd) || + unit != thd->variables.wsrep_trx_fragment_unit || + thd->variables.wsrep_trx_fragment_size == 0 || + thd->get_stmt_da()->is_error()) + { +#if 0 + WSREP_DEBUG("wsrep_SR_step: skip, frag_size: %lu is_error: %d", + thd->variables.wsrep_trx_fragment_size, + thd->get_stmt_da()->is_error()); +#endif /* 0 */ + DBUG_RETURN(0); + } + + /* + Flush pending rows event into IO cache buffer + */ + thd->binlog_flush_pending_rows_event(true); + + wsrep_trx_status ret= WSREP_TRX_OK; + uint written= (wsrep_get_trans_cache_position(thd) + - wsrep_get_fragment_base(thd)); + bool replicate= false; + + switch (thd->variables.wsrep_trx_fragment_unit) + { + case WSREP_FRAG_BYTES: + if (written >= thd->variables.wsrep_trx_fragment_size) + replicate= true; + break; + case WSREP_FRAG_ROWS: + case WSREP_FRAG_STATEMENTS: + wsrep_append_fill_rate(thd, 1); + if (wsrep_get_fragment_fill(thd) >= thd->variables.wsrep_trx_fragment_size) + replicate= true; + break; + default: + wsrep_append_fill_rate(thd, 1); + replicate= true; + DBUG_ASSERT(0); + } + + if (replicate) + { + WSREP_DEBUG("fragment fill: %lu fragment unit: %lu fragment size: %lu written: %u", + wsrep_get_fragment_fill(thd), + thd->variables.wsrep_trx_fragment_unit, + thd->variables.wsrep_trx_fragment_size, + written); + + ret= wsrep_replicate_fragment(thd); + if (ret == WSREP_TRX_OK) + { + wsrep_reset_fragment_fill(thd, 0); + wsrep_step_fragment_base(thd, written); + } + } + + if (ret) + { + if (!thd->get_stmt_da()->is_error()) + { + wsrep_override_error(thd, ER_ERROR_DURING_COMMIT, + wsrep_trx_status_to_wsrep_status(ret)); + } + } + + DBUG_RETURN(ret); +} + +bool wsrep_replicate_GTID(THD *thd) +{ + if (thd->slave_thread) + { + WSREP_DEBUG("GTID replication"); + DBUG_ASSERT (WSREP_UNDEFINED_TRX_ID == thd->wsrep_ws_handle.trx_id); + thd->set_wsrep_next_trx_id(thd->query_id); + (void)wsrep_ws_handle_for_trx(&thd->wsrep_ws_handle, + thd->wsrep_next_trx_id()); + DBUG_ASSERT (WSREP_UNDEFINED_TRX_ID != thd->wsrep_ws_handle.trx_id); + + int rcode= wsrep_certify(thd); + if (rcode) + { + WSREP_INFO("GTID replication failed: %d", rcode); + if (wsrep->commit_order_enter(wsrep, &thd->wsrep_ws_handle, + &thd->wsrep_trx_meta)) + { + WSREP_ERROR("wsrep::commit_order_enter fail: %llu %d", + (long long)thd->thread_id, thd->get_stmt_da()->status()); + } + + if (wsrep->commit_order_leave(wsrep, &thd->wsrep_ws_handle, + &thd->wsrep_trx_meta, NULL)) + { + WSREP_ERROR("wsrep::commit_order_leave fail: %llu %d", + (long long)thd->thread_id, thd->get_stmt_da()->status()); + } + + thd->wsrep_replicate_GTID= false; + my_message(ER_ERROR_DURING_COMMIT, + "WSREP GTID replication was interrupted", MYF(0)); + + return true; + } + } + thd->wsrep_replicate_GTID= false; + return false; +} + + +/* + Utility methods to be called from hooks + */ + +/* + Log some THD info and called context + */ +static void wsrep_log_thd(THD* thd, bool is_real_trans, const char *function) +{ + char message[10]; + snprintf(message, sizeof(message), "real: %d", is_real_trans); + message[sizeof(message) - 1] = '\0'; + wsrep_log_thd(thd, message, function); +} + + +/* + Determine if the hook should be run + + @return 0 Failure + @return 1 Success +*/ +static int wsrep_run_hook(const THD* thd, bool is_real_trans, + bool for_real_trans) +{ + return (WSREP(thd) && /* THD is non NULL, wsrep is enabled for thd + and is client thread */ + thd->wsrep_exec_mode != TOTAL_ORDER && /* not TOI execution */ + thd->wsrep_exec_mode != REPL_RECV && /* not applier or replayer */ + (!for_real_trans || is_real_trans) && + !(for_real_trans && /* CTAS SELECT phase */ + WSREP_BINLOG_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_STMT && + thd->lex->sql_command == SQLCOM_CREATE_TABLE && + thd->lex->current_select->item_list.elements) + ); +} + +static inline +int wsrep_is_effective_not_to_replay(THD *thd) +{ + mysql_mutex_assert_owner(&thd->LOCK_wsrep_thd); + int ret= ( + /* effective */ + thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID && + /* not to replay */ + thd->wsrep_conflict_state() != MUST_REPLAY + ); + return ret; +} + + +int wsrep_after_row(THD* thd, bool all) +{ + DBUG_ENTER("wsrep_after_row"); + + bool is_real_trans= (all || thd->transaction.all.ha_list == 0); + + /* + We want to run this hook for each row, not just ones which + end autocommits or transactions. + */ + if (!wsrep_run_hook(thd, is_real_trans, false)) + { + DBUG_RETURN(0); + } + + +#if 0 + /* + Logging this hook is disabled, it gets very verbose. + */ + wsrep_log_thd(thd, is_real_trans, "wsrep_after_row enter"); +#endif /* 0 */ + int ret= 0; + + /* + TODO: Move this before row operation, maybe before_row() hook. + */ + if (!wsrep_certify_nonPK) + { + for (TABLE* table= thd->open_tables; table != NULL; table= table->next) + { + if (table->key_info == NULL || table->s->primary_key == MAX_KEY) + { + WSREP_DEBUG("No primary key found for table %s.%s", + table->s->db.str, table->s->table_name.str); + ret= 1; + break; + } + } + } + + if (!ret) + { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state() == NO_CONFLICT) + { + ret|= wsrep_SR_step(thd, WSREP_FRAG_BYTES); + ret|= wsrep_SR_step(thd, WSREP_FRAG_ROWS); + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } +#if 0 + /* + Logging this hook is disabled, it gets very verbose. + */ + wsrep_log_thd(thd, is_real_trans, "wsrep_after_row leave"); +#endif /* 0 */ + + + DBUG_RETURN(ret); +} + +int wsrep_before_prepare(THD* thd, bool all) +{ + DBUG_ENTER("wsrep_before_prepare"); + + bool is_real_trans= (all || thd->transaction.all.ha_list == 0); + + if (!wsrep_run_hook(thd, is_real_trans, true)) + { + DBUG_RETURN(0); + } + + if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID) + { + wsrep_log_thd(thd, is_real_trans, "wsrep_before_prepare enter"); + } + + int ret= 0; + DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_STATE); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (wsrep_is_effective_not_to_replay(thd)) + { + if (thd->wsrep_is_streaming()) + { + DBUG_EXECUTE_IF("crash_last_fragment_commit_before_fragment_removal", + DBUG_SUICIDE();); + + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + /* + We don't support implicit commit for SR transactions. + */ + if (stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_BEGIN)) + { + wsrep_override_error(thd, ER_ERROR_DURING_COMMIT); + ret= 1; + } + else + { + /* + Disable SR temporarily in order to avoid SR step from + after_row() hook when deleting fragments. + */ + ulong frag_size_orig= thd->variables.wsrep_trx_fragment_size; + thd->variables.wsrep_trx_fragment_size= 0; + wsrep_remove_SR_fragments(thd); + thd->variables.wsrep_trx_fragment_size= frag_size_orig; + } + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + DBUG_EXECUTE_IF("crash_last_fragment_commit_after_fragment_removal", + DBUG_SUICIDE();); + } + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID) + { + wsrep_log_thd(thd, is_real_trans, "wsrep_before_prepare leave"); + } + DBUG_RETURN(ret); +} + +int wsrep_after_prepare(THD* thd, bool all) +{ + DBUG_ENTER("wsrep_after_prepare"); + + bool is_real_trans= (all || thd->transaction.all.ha_list == 0); + + if (!wsrep_run_hook(thd, is_real_trans, true)) + { + DBUG_RETURN(0); + } + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID) + { + wsrep_log_thd(thd, is_real_trans, "wsrep_after_prepare enter"); + } + + DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_STATE); + /* + thd->wsrep_exec_mode will be set in wsrep_certify() according + to outcome + */ + int ret= 1; + + if (wsrep_is_effective_not_to_replay(thd)) + { + if (thd->wsrep_conflict_state() == NO_CONFLICT) + { + ret= wsrep_certify(thd); + if (ret) + { + DBUG_ASSERT(thd->wsrep_conflict_state() == MUST_REPLAY || + thd->get_stmt_da()->is_error()); + } + } + else + { + /* + BF aborted before pre commit, set state to aborting + and return error to trigger rollback. + */ + DBUG_ASSERT(thd->wsrep_conflict_state() == MUST_ABORT); + wsrep_override_error(thd, ER_LOCK_DEADLOCK); + } + } + if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID) + { + wsrep_log_thd(thd, is_real_trans, "wsrep_after_prepare leave"); + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + DBUG_RETURN(ret); +} + +int wsrep_before_commit(THD* thd, bool all) +{ + DBUG_ENTER("wsrep_before_commit"); + + bool is_real_trans= (all || thd->transaction.all.ha_list == 0); + + /* + Applier/replayer codepath + */ + if (thd->wsrep_exec_mode == REPL_RECV) + { + wsrep_log_thd(thd, is_real_trans, "wsrep_before_commit enter"); + if (is_real_trans) + { + DBUG_ASSERT(thd->wsrep_trx_must_order_commit()); + if (wsrep->commit_order_enter(wsrep, &thd->wsrep_ws_handle, + &thd->wsrep_trx_meta) != WSREP_OK) + { + WSREP_ERROR("Failed to enter applier commit order critical section"); + DBUG_RETURN(1); + } + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_COMMITTING); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } + wsrep_log_thd(thd, is_real_trans, "wsrep_before_commit leave"); + DBUG_RETURN(0); + } + + + if (!wsrep_run_hook(thd, is_real_trans, true)) + { + DBUG_RETURN(0); + } + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID) + { + wsrep_log_thd(thd, is_real_trans, "wsrep_before_commit enter"); + } + + int ret= 0; + if (thd->wsrep_exec_mode == LOCAL_STATE) + { + /* + We got here without having prepare phase first. This may + happen for example via trans_commit_stmt() -> tc_log->commit(thd, false) + in case of autocommit DML and binlog_format = STATEMENT. + */ + if (wsrep_is_effective_not_to_replay(thd)) + { + if (thd->wsrep_conflict_state() == NO_CONFLICT) + { + ret= wsrep_certify(thd); + } + else + { + /* + BF aborted before pre commit, set state to aborting + and return error to trigger rollback. + */ + DBUG_ASSERT(thd->wsrep_conflict_state() == MUST_ABORT); + wsrep_override_error(thd, ER_LOCK_DEADLOCK); + ret= 1; + } + } + } + + + if (!ret && wsrep_is_effective_not_to_replay(thd)) + { + if (thd->wsrep_conflict_state() == MUST_ABORT) + { + ret= 1; + } + else + { + DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + wsrep_status_t rcode= wsrep->commit_order_enter(wsrep, + &thd->wsrep_ws_handle, + &thd->wsrep_trx_meta); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + switch (rcode) + { + case WSREP_OK: + wsrep_xid_init(&thd->wsrep_xid, thd->wsrep_trx_meta.gtid.uuid, + thd->wsrep_trx_meta.gtid.seqno); + break; + case WSREP_BF_ABORT: + DBUG_ASSERT(wsrep_thd_trx_seqno(thd) > 0); + if (thd->wsrep_conflict_state() != MUST_ABORT) + thd->set_wsrep_conflict_state(MUST_ABORT); + mysql_mutex_lock(&LOCK_wsrep_replaying); + ++wsrep_replaying; + mysql_mutex_unlock(&LOCK_wsrep_replaying); + ret= 1; + break; + default: + WSREP_ERROR("Could not enter commit order critical section"); + abort(); + } + } + } + + DBUG_ASSERT(ret || + thd->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID || + thd->wsrep_exec_mode == LOCAL_COMMIT); + + if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID) + { + wsrep_log_thd(thd, is_real_trans, "wsrep_before_commit leave"); + } + + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + DBUG_RETURN(ret); +} + +int wsrep_ordered_commit(THD* thd, bool all, const wsrep_apply_error& err) +{ + DBUG_ENTER("wsrep_ordered_commit"); + + bool is_real_trans= (all || thd->transaction.all.ha_list == 0); + + /* + Applier/replayer codepath + */ + if (thd->wsrep_exec_mode == REPL_RECV) + { + int ret= 0; + wsrep_log_thd(thd, is_real_trans, "wsrep_ordered_commit enter"); + if (is_real_trans) + { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + bool run_commit_order_leave= + (thd->wsrep_query_state() != QUERY_ORDERED_COMMIT); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + if (run_commit_order_leave) + { + wsrep_buf_t const err_buf= err.get_buf(); + wsrep_status_t const rcode= + wsrep->commit_order_leave(wsrep, &thd->wsrep_ws_handle, + &thd->wsrep_trx_meta, &err_buf); + + if (rcode != WSREP_OK) + { + DBUG_ASSERT(rcode == WSREP_NODE_FAIL); + if (err.is_null()) + { + WSREP_ERROR("Failed to leave commit order critical section, " + "rcode: %d", rcode); + } + else + { + WSREP_WARN("Replication can't continue due to the error in a " + "writeset apply operation: %s", err.c_str()); + } + ret= 1; + } + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_ORDERED_COMMIT); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } + } + DBUG_RETURN(ret); + } + + if (!wsrep_run_hook(thd, is_real_trans, true)) + { + DBUG_RETURN(0); + } + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID) + { + wsrep_log_thd(thd, is_real_trans, "wsrep_ordered_commit enter"); + } + + DBUG_ASSERT(thd->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID || + (thd->wsrep_exec_mode == LOCAL_COMMIT && + thd->wsrep_query_state() == QUERY_COMMITTING)); + DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT); + if (wsrep_is_effective_not_to_replay(thd)) + { + thd->wsrep_SR_fragments.clear(); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + if (wsrep_thd_trx_seqno(thd) != WSREP_SEQNO_UNDEFINED && + wsrep->commit_order_leave(wsrep, &thd->wsrep_ws_handle, + &thd->wsrep_trx_meta, NULL)) + { + WSREP_ERROR("wsrep::commit_order_leave fail: %llu %d", + (long long)thd->thread_id, thd->get_stmt_da()->status()); + } + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_ORDERED_COMMIT); + } + + if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID) + { + wsrep_log_thd(thd, is_real_trans, "wsrep_ordered_commit leave"); + } + + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + DBUG_RETURN(0); +} + +int wsrep_after_commit(THD* thd, bool all) +{ + DBUG_ENTER("wsrep_after_commit"); + + bool is_real_trans= (all || thd->transaction.all.ha_list == 0); + + if (!wsrep_run_hook(thd, is_real_trans, true)) + { + DBUG_RETURN(0); + } + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID) + { + wsrep_log_thd(thd, is_real_trans, "wsrep_after_commit enter"); + } + + DBUG_ASSERT(thd->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID || + (thd->wsrep_exec_mode == LOCAL_COMMIT && + (thd->wsrep_query_state() == QUERY_COMMITTING || + thd->wsrep_query_state() == QUERY_ORDERED_COMMIT))); + DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT || + thd->wsrep_conflict_state() == MUST_ABORT); + + if (wsrep_is_effective_not_to_replay(thd)) + { + if (thd->wsrep_query_state() == QUERY_COMMITTING) + { + thd->wsrep_SR_fragments.clear(); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + if (wsrep_thd_trx_seqno(thd) != WSREP_SEQNO_UNDEFINED && + wsrep->commit_order_leave(wsrep, &thd->wsrep_ws_handle, + &thd->wsrep_trx_meta, NULL)) + { + WSREP_ERROR("wsrep::commit_order_leave fail: %llu %d", + (long long)thd->thread_id, thd->get_stmt_da()->status()); + } + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_ORDERED_COMMIT); + } + + DBUG_ASSERT(thd->wsrep_query_state() == QUERY_ORDERED_COMMIT); + + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + if (wsrep->release(wsrep, &thd->wsrep_ws_handle)) + { + WSREP_WARN("wsrep::release fail: %lld %d", + (long long)thd->thread_id, thd->get_stmt_da()->status()); + } + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_EXEC); + } + + if (thd->wsrep_conflict_state() == MUST_ABORT) + { + assert(0); + WSREP_LOG_THD(thd, "BF aborted at commit phase"); + thd->killed= NOT_KILLED; + thd->set_wsrep_conflict_state(NO_CONFLICT); + } + + wsrep_cleanup_transaction(thd); + + if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID) + { + wsrep_log_thd(thd, is_real_trans, "wsrep_after_commit leave"); + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + DBUG_RETURN(0); +} + +int wsrep_before_rollback(THD* thd, bool all) +{ + DBUG_ENTER("wsrep_before_rollback"); + + bool is_real_trans= (all || thd->transaction.all.ha_list == 0); + + if (!wsrep_run_hook(thd, is_real_trans, false)) + { + DBUG_RETURN(0); + } + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID) + { + (void)wsrep_ws_handle_for_trx(&thd->wsrep_ws_handle, + thd->wsrep_next_trx_id()); + + if (thd->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID) + { + WSREP_DEBUG("wsrep_before_rollback: setting trx_id to undefined, thd %llu %s", + thd->thread_id, thd->query()); + } + } + + if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID) + { + wsrep_log_thd(thd, is_real_trans, "wsrep_before_rollback enter"); + } + + if (thd->wsrep_query_state() == QUERY_COMMITTING) + { + DBUG_ASSERT(thd->wsrep_conflict_state() == MUST_ABORT); + WSREP_DEBUG("Query aborted while committing"); + thd->set_wsrep_query_state(QUERY_EXEC); + thd->set_wsrep_conflict_state(MUST_REPLAY); + thd->wsrep_exec_mode= LOCAL_STATE; + } + + if (thd->wsrep_exec_mode != LOCAL_ROLLBACK && + wsrep_is_effective_not_to_replay(thd) && + (is_real_trans || + (thd->wsrep_is_streaming() && + (!wsrep_stmt_rollback_is_safe(thd) || + thd->wsrep_conflict_state() != NO_CONFLICT)))) + { + if (thd->wsrep_is_streaming() && + /* + Cert failure will generate implicit rollback event on slaves + + TODO: Need to do SR table cleanup on certification failure here. + */ + thd->wsrep_conflict_state() != CERT_FAILURE && + thd->wsrep_SR_rollback_replicated_for_trx != thd->wsrep_trx_id()) + { + wsrep_prepare_SR_trx_info_for_rollback(thd); + thd->wsrep_SR_rollback_replicated_for_trx= thd->wsrep_trx_id(); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + DEBUG_SYNC(thd, "wsrep_before_SR_rollback"); + WSREP_DEBUG("Replicating rollback for %ld %ld", + thd->thread_id, thd->wsrep_trx_id()); + wsrep_status_t rcode= wsrep->rollback(wsrep, + thd->wsrep_trx_id(), NULL); + if (rcode != WSREP_OK) + { + WSREP_WARN("failed to send SR rollback for %lld", thd->thread_id); + } + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + } + thd->wsrep_exec_mode= LOCAL_ROLLBACK; + } + + if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID) + { + wsrep_log_thd(thd, is_real_trans, "wsrep_before_rollback leave"); + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + DBUG_RETURN(0); +} + +int wsrep_after_rollback(THD* thd, bool all) +{ + DBUG_ENTER("wsrep_after_rollback"); + + bool is_real_trans= (all || thd->transaction.all.ha_list == 0); + + if (!wsrep_run_hook(thd, is_real_trans, false)) + { + DBUG_RETURN(0); + } + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID) + { + wsrep_log_thd(thd, is_real_trans, "wsrep_after_rollback enter"); + } + + DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT || /* voluntary or stmt rollback */ + thd->wsrep_conflict_state() == MUST_ABORT || /* BF abort */ + thd->wsrep_conflict_state() == ABORTING || /* called from wsrep_client_rollback() */ + thd->wsrep_conflict_state() == CERT_FAILURE || /* cert failure */ + thd->wsrep_conflict_state() == MUST_REPLAY || /* BF abort with successful repl */ + (thd->wsrep_conflict_state() == ABORTED) /* trans_rollback_stmt() from mysql_exec_command() */ + ); + + if (!is_real_trans) + { + /* + Statement rollback + */ + if ((thd->wsrep_is_streaming() && !wsrep_stmt_rollback_is_safe(thd))) + { + /* + Statement rollback is not safe, do full rollback and report to client. + */ + if (thd->wsrep_conflict_state() == NO_CONFLICT) + { + /* + If the statement rollback is due to an error, such as ER_DUP_ENTRY, + the client may not expect a full transaction rollback. + Set the conflict state to must abort here so that after_command() + hook will override the error to ER_LOCK_DEADLOCK. + */ + thd->set_wsrep_conflict_state(MUST_ABORT); + } + + /* + From trans_rollback() + */ + thd->server_status&= + ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + /* + Calling ha_rollback_trans() here will call rollback hooks recursively. + */ + ha_rollback_trans(thd, TRUE); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->variables.option_bits&= ~OPTION_BEGIN; + //thd->transaction.all.reset_unsafe_rollback_flags(); + thd->transaction.all.m_unsafe_rollback_flags= 0; + thd->lex->start_transaction_opt= 0; + } + } + else + { + if (thd->wsrep_conflict_state() == ABORTED) + { + thd->wsrep_exec_mode= LOCAL_ROLLBACK; + } + if (wsrep_is_effective_not_to_replay(thd)) + { + /* + Must have gone through before_rollback() hook at least once. + */ + DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_ROLLBACK); + } + } + + if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID) + { + wsrep_log_thd(thd, is_real_trans, "wsrep_after_rollback leave"); + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + DBUG_RETURN(0); +} + +int wsrep_after_command(THD* thd, bool all) +{ + DBUG_ENTER("wsrep_after_command"); + + bool is_real_trans= (all || thd->transaction.all.ha_list == 0); + + /* + We want to run this hook for each command, not just ones which + end autocommits or transactions. + */ + if (!wsrep_run_hook(thd, is_real_trans, false)) + { + DBUG_RETURN(0); + } + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + + if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID) + { + wsrep_log_thd(thd, is_real_trans, "wsrep_after_command enter"); + } + + DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_STATE || + thd->wsrep_exec_mode == LOCAL_ROLLBACK); + + int ret= 0; + + switch (thd->wsrep_exec_mode) + { + case LOCAL_STATE: + /* + Run SR step if + - No conflict detected + - Trnsaction is active, it has acquired trx_id + - Not read-only command + */ + if (thd->wsrep_conflict_state() == NO_CONFLICT && + thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID && + thd->lex->sql_command != SQLCOM_SELECT) + { + ret|= wsrep_SR_step(thd, WSREP_FRAG_BYTES); + ret|= wsrep_SR_step(thd, WSREP_FRAG_STATEMENTS); + } + break; + case LOCAL_ROLLBACK: + { + bool should_retry= false; + const bool forced_rollback(thd->wsrep_conflict_state() == MUST_ABORT || + thd->wsrep_conflict_state() == CERT_FAILURE); + + DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT || + thd->wsrep_conflict_state() == MUST_ABORT || + thd->wsrep_conflict_state() == CERT_FAILURE); + /* + If conflict state is NO_CONFLICT the transaction was either + voluntary or done due to deadlock. + */ + if (forced_rollback) + { + should_retry= !( + thd->wsrep_is_streaming() || // SR transactions do not retry + thd->spcont // SP code not patched to handle retry + ); + wsrep_client_rollback(thd, false); + } + wsrep_post_rollback(thd); + if (forced_rollback) + { + wsrep_override_error(thd, ER_LOCK_DEADLOCK); + } + wsrep_cleanup_transaction(thd); + DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_STATE); + DBUG_ASSERT(thd->wsrep_conflict_state() == NO_CONFLICT); + /* + Retry autocommit in case of deadlock error, usually seen + as ER_LOCK_DEADLOCK, sometimes as ER_QUERY_INTERRUPTED. + */ + if (should_retry && thd->get_stmt_da()->is_error() && + (thd->get_stmt_da()->sql_errno() == ER_LOCK_DEADLOCK || + thd->get_stmt_da()->sql_errno() == ER_QUERY_INTERRUPTED)) + { + thd->set_wsrep_conflict_state(RETRY_AUTOCOMMIT); + } + } + break; + default: + break; + } + + if (thd->wsrep_conflict_state() == MUST_ABORT || + thd->wsrep_conflict_state() == CERT_FAILURE) + { + wsrep_client_rollback(thd); + wsrep_post_rollback(thd); + wsrep_override_error(thd, ER_LOCK_DEADLOCK); + wsrep_cleanup_transaction(thd); + } + + if (thd->wsrep_conflict_state() == MUST_REPLAY && + !thd->spcont) + { + /* + BF aborted during commit, must replay + */ + wsrep_replay_transaction(thd); + } + + if (thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID) + { + wsrep_log_thd(thd, is_real_trans, "wsrep_after_command leave"); + } + + + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + DBUG_RETURN(ret); +} + +int wsrep_before_GTID_binlog(THD* thd, bool all) +{ + DBUG_ENTER("wsrep_before_GTID_binlogt"); + int ret= 0; + + bool is_real_trans= (all || thd->transaction.all.ha_list == 0); + + if (!wsrep_run_hook(thd, is_real_trans, true)) + { + DBUG_RETURN(0); + } + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (wsrep_replicate_GTID(thd)) + { + ret = 1; + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + wsrep_status_t rcode; + if (!ret && + (rcode = wsrep->commit_order_enter(wsrep, &thd->wsrep_ws_handle, + &thd->wsrep_trx_meta))) + { + WSREP_ERROR("wsrep::commit_order_enter fail: %llu %d", + (long long)thd->thread_id, rcode); + ret= 1; + } + + if (!ret && + (rcode = wsrep->commit_order_leave(wsrep, &thd->wsrep_ws_handle, + &thd->wsrep_trx_meta, NULL))) + { + WSREP_ERROR("wsrep::commit_order_leave fail: %llu %d", + (long long)thd->thread_id, rcode); + ret= 1; + } + + if (!ret) + { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->set_wsrep_query_state(QUERY_ORDERED_COMMIT); + thd->set_wsrep_query_state(QUERY_EXEC); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } + + if (wsrep->release(wsrep, &thd->wsrep_ws_handle)) + { + WSREP_WARN("wsrep::release fail: %lld %d", + (long long)thd->thread_id, thd->get_stmt_da()->status()); + } + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + wsrep_cleanup_transaction(thd); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + DBUG_RETURN(ret); +} + +int wsrep_register_trans_observer(void *p) +{ + return 0; +} + +int wsrep_unregister_trans_observer(void *p) +{ + return 0; +} diff --git a/sql/wsrep_trans_observer.h b/sql/wsrep_trans_observer.h new file mode 100644 index 00000000000..91b6d25eb78 --- /dev/null +++ b/sql/wsrep_trans_observer.h @@ -0,0 +1,117 @@ +/* Copyright 2016 Codership Oy <http://www.codership.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef WSREP_TRANS_OBSERVER_H +#define WSREP_TRANS_OBSERVER_H + +#include "my_global.h" +#include "wsrep_applier.h" /* wsrep_apply_error */ + +class THD; + +/* + Called after each row operation. + + Return zero on succes, non-zero on failure. + */ +int wsrep_after_row(THD*, bool); + +/* + Called before the transaction is prepared. + + Return zero on succes, non-zero on failure. + */ +int wsrep_before_prepare(THD*, bool); + +/* + Called after the transaction has been prepared. + + Return zero on succes, non-zero on failure. + */ +int wsrep_after_prepare(THD*, bool); + + +/* + Called before the transaction is committed. + + This function must be called from both client and + applier contexts before commit. + + Return zero on succes, non-zero on failure. + */ +int wsrep_before_commit(THD*, bool); + +/* + Called after the transaction has been ordered for commit. + + This function must be called from both client and + applier contexts after the commit has been ordered. + + @param thd Pointer to THD + @param all + @param err Error buffer in case of applying error + + Return zero on succes, non-zero on failure. + */ +int wsrep_ordered_commit(THD* thd, bool all, const wsrep_apply_error& err); + +/* + Called after the transaction has been committed. + + Return zero on succes, non-zero on failure. + */ +int wsrep_after_commit(THD*, bool); + +/* + Called before the transaction is rolled back. + + Return zero on succes, non-zero on failure. + */ +int wsrep_before_rollback(THD*, bool); + +/* + Called after the transaction has been rolled back. + + Return zero on succes, non-zero on failure. + */ +int wsrep_after_rollback(THD*, bool); + +/* + Called after each command. + + Return zero on success, non-zero on failure. + */ +int wsrep_after_command(THD*, bool); + +/* + Called before a GTID is logged into binlog without committing a + transaction. + + Return zero on success, non-zero on failure. + */ +int wsrep_before_GTID_binlog(THD* thd, bool); + + +/* + Register wsrep transaction observer hooks +*/ +int wsrep_register_trans_observer(void *p); + +/* + Unregister wsrep transaction observer hooks + */ +int wsrep_unregister_trans_observer(void *p); + +#endif /* WSREP_TRANS_OBSERVER */ diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc index 3c341e222b3..e9dad5f1912 100644 --- a/sql/wsrep_utils.cc +++ b/sql/wsrep_utils.cc @@ -21,6 +21,7 @@ #endif #include "mariadb.h" +#include "my_pthread.h" #include "wsrep_utils.h" #include "wsrep_mysqld.h" diff --git a/sql/wsrep_utils.h b/sql/wsrep_utils.h index 277cea9dc31..bb3203c87e9 100644 --- a/sql/wsrep_utils.h +++ b/sql/wsrep_utils.h @@ -21,6 +21,27 @@ unsigned int wsrep_check_ip (const char* const addr, bool *is_ipv6); size_t wsrep_guess_ip (char* buf, size_t buf_len); +namespace wsp { +class node_status +{ +public: + node_status() : status(WSREP_MEMBER_UNDEFINED) {} + void set(wsrep_member_status_t new_status, + const wsrep_view_info_t* view = 0) + { + if (status != new_status || 0 != view) + { + wsrep_notify_status(new_status, view); + status = new_status; + } + } + wsrep_member_status_t get() const { return status; } +private: + wsrep_member_status_t status; +}; +} /* namespace wsp */ + +extern wsp::node_status local_status; /* returns the length of the host part of the address string */ size_t wsrep_host_len(const char* addr, size_t addr_len); @@ -219,6 +240,7 @@ public: return &member_info_; } +#ifdef WITH_WSREP int lock() { return mysql_mutex_lock(&LOCK_wsrep_config_state); @@ -228,6 +250,7 @@ public: { return mysql_mutex_unlock(&LOCK_wsrep_config_state); } +#endif private: wsrep_view_info_t view_; @@ -314,6 +337,17 @@ private: char* string_; }; +/* scope level lock */ +class auto_lock +{ +public: + auto_lock(mysql_mutex_t* m) : m_(m) { mysql_mutex_lock(m_); } + ~auto_lock() { mysql_mutex_unlock(m_); } +private: + mysql_mutex_t& operator =(mysql_mutex_t&); + mysql_mutex_t* const m_; +}; + #ifdef REMOVED class lock { diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 7fe120beb8e..758a804d384 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -28,8 +28,6 @@ ulong wsrep_reject_queries; -static long wsrep_prev_slave_threads = wsrep_slave_threads; - int wsrep_init_vars() { wsrep_provider = my_strdup(WSREP_NONE, MYF(MY_WME)); @@ -157,15 +155,15 @@ bool wsrep_start_position_verify (const char* start_str) static -bool wsrep_set_local_position(const char* const value, size_t length, - bool const sst) +bool wsrep_set_local_position(THD* thd, const char* const value, + size_t length, bool const sst) { wsrep_uuid_t uuid; size_t const uuid_len = wsrep_uuid_scan(value, length, &uuid); wsrep_seqno_t const seqno = strtoll(value + uuid_len + 1, NULL, 10); if (sst) { - return wsrep_sst_received (wsrep, uuid, seqno, NULL, 0, false); + wsrep_sst_received (thd, wsrep, uuid, seqno, NULL, 0, false); } else { // initialization local_uuid = uuid; @@ -194,7 +192,7 @@ bool wsrep_start_position_check (sys_var *self, THD* thd, set_var* var) As part of further verification, we try to update the value and catch errors (if any). */ - if (wsrep_set_local_position(var->save_result.string_value.str, + if (wsrep_set_local_position(thd, var->save_result.string_value.str, var->save_result.string_value.length, true)) { @@ -226,7 +224,7 @@ bool wsrep_start_position_init (const char* val) return true; } - if (wsrep_set_local_position (val, strlen(val), false)) + if (wsrep_set_local_position (NULL, val, strlen(val), false)) { WSREP_ERROR("Failed to set initial wsep_start_position: %s", val); return true; @@ -332,8 +330,6 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type) { bool rcode= false; - bool wsrep_on_saved= thd->variables.wsrep_on; - thd->variables.wsrep_on= false; WSREP_DEBUG("wsrep_provider_update: %s", wsrep_provider); @@ -344,9 +340,15 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type) Note: releasing LOCK_global_system_variables may cause race condition, if there can be several concurrent clients changing wsrep_provider */ + mysql_mutex_assert_not_owner(&LOCK_wsrep_thd_pool); mysql_mutex_unlock(&LOCK_global_system_variables); wsrep_stop_replication(thd); - mysql_mutex_lock(&LOCK_global_system_variables); + + /* provider status variables are allocated in provider library + and need to freed here, otherwise a dangling reference to + wsrep_status_vars would remain in THD + */ + wsrep_free_status(thd); if (wsrep_inited == 1) wsrep_deinit(false); @@ -364,10 +366,10 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type) // we sure don't want to use old address with new provider wsrep_cluster_address_init(NULL); wsrep_provider_options_init(NULL); + if (!rcode) + refresh_provider_options(); - thd->variables.wsrep_on= wsrep_on_saved; - - refresh_provider_options(); + mysql_mutex_lock(&LOCK_global_system_variables); return rcode; } @@ -468,8 +470,6 @@ bool wsrep_cluster_address_check (sys_var *self, THD* thd, set_var* var) bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type) { - bool wsrep_on_saved; - /* Do not proceed if wsrep provider is not loaded. */ if (!wsrep) { @@ -477,9 +477,6 @@ bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type) return false; } - wsrep_on_saved= thd->variables.wsrep_on; - thd->variables.wsrep_on= false; - /* stop replication is heavy operation, and includes closing all client connections. Closing clients may need to get LOCK_global_system_variables at least in MariaDB. @@ -487,16 +484,10 @@ bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type) Note: releasing LOCK_global_system_variables may cause race condition, if there can be several concurrent clients changing wsrep_provider */ + mysql_mutex_assert_not_owner(&LOCK_wsrep_thd_pool); mysql_mutex_unlock(&LOCK_global_system_variables); wsrep_stop_replication(thd); - /* - Unlock and lock LOCK_wsrep_slave_threads to maintain lock order & avoid - any potential deadlock. - */ - mysql_mutex_unlock(&LOCK_wsrep_slave_threads); - mysql_mutex_lock(&LOCK_global_system_variables); - mysql_mutex_lock(&LOCK_wsrep_slave_threads); if (wsrep_start_replication()) { @@ -504,7 +495,13 @@ bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type) wsrep_create_appliers(wsrep_slave_threads); } - thd->variables.wsrep_on= wsrep_on_saved; + /* locking order to be enforced is: + 1. LOCK_global_system_variables + 2. LOCK_wsrep_slave_threads + */ + mysql_mutex_unlock(&LOCK_wsrep_slave_threads); + mysql_mutex_lock(&LOCK_global_system_variables); + mysql_mutex_lock(&LOCK_wsrep_slave_threads); return false; } @@ -594,8 +591,8 @@ void wsrep_node_address_init (const char* value) static void wsrep_slave_count_change_update () { - wsrep_slave_count_change += (wsrep_slave_threads - wsrep_prev_slave_threads); - wsrep_prev_slave_threads = wsrep_slave_threads; + // wsrep_running_threads = appliers threads + 2 rollbacker threads + wsrep_slave_count_change = (wsrep_slave_threads - wsrep_running_threads + 2); } bool wsrep_slave_threads_update (sys_var *self, THD* thd, enum_var_type type) @@ -667,6 +664,34 @@ bool wsrep_max_ws_size_check(sys_var *self, THD* thd, set_var* var) return false; } +bool wsrep_trx_fragment_size_check (sys_var *self, THD* thd, set_var* var) +{ + if (var->value == NULL) { + return false; + } + + const ulong new_trx_fragment_size = var->value->val_uint(); + + if (!WSREP(thd) && new_trx_fragment_size > 0) { + push_warning (thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_VALUE_FOR_VAR, + "Cannot set 'wsrep_trx_fragment_size' to a value other than " + "0 because wsrep is switched off."); + return true; + } + + if (new_trx_fragment_size > 0 && !wsrep_provider_is_SR_capable()) { + push_warning (thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_VALUE_FOR_VAR, + "Cannot set 'wsrep_trx_fragment_size' to a value other than " + "0 because the wsrep_provider does not support streaming " + "replication."); + return true; + } + + return false; +} + bool wsrep_max_ws_size_update (sys_var *self, THD *thd, enum_var_type) { DBUG_ASSERT(wsrep); @@ -687,16 +712,17 @@ bool wsrep_max_ws_size_update (sys_var *self, THD *thd, enum_var_type) static SHOW_VAR wsrep_status_vars[]= { {"connected", (char*) &wsrep_connected, SHOW_BOOL}, - {"ready", (char*) &wsrep_ready, SHOW_BOOL}, + {"ready", (char*) &wsrep_show_ready, SHOW_FUNC}, {"cluster_state_uuid",(char*) &wsrep_cluster_state_uuid,SHOW_CHAR_PTR}, {"cluster_conf_id", (char*) &wsrep_cluster_conf_id, SHOW_LONGLONG}, {"cluster_status", (char*) &wsrep_cluster_status, SHOW_CHAR_PTR}, {"cluster_size", (char*) &wsrep_cluster_size, SHOW_LONG_NOFLUSH}, {"local_index", (char*) &wsrep_local_index, SHOW_LONG_NOFLUSH}, - {"local_bf_aborts", (char*) &wsrep_show_bf_aborts, SHOW_SIMPLE_FUNC}, + {"local_bf_aborts", (char*) &wsrep_show_bf_aborts, SHOW_FUNC}, {"provider_name", (char*) &wsrep_provider_name, SHOW_CHAR_PTR}, {"provider_version", (char*) &wsrep_provider_version, SHOW_CHAR_PTR}, {"provider_vendor", (char*) &wsrep_provider_vendor, SHOW_CHAR_PTR}, + {"wsrep_provider_capabilities", (char*) &wsrep_provider_capabilities, SHOW_CHAR_PTR}, {"thread_count", (char*) &wsrep_running_threads, SHOW_LONG_NOFLUSH} }; @@ -705,6 +731,30 @@ static int show_var_cmp(const void *var1, const void *var2) return strcasecmp(((SHOW_VAR*)var1)->name, ((SHOW_VAR*)var2)->name); } +/* + * Status variables stuff below + */ +static inline void +wsrep_assign_to_mysql (SHOW_VAR* mysql, wsrep_stats_var* wsrep) +{ + mysql->name = wsrep->name; + switch (wsrep->type) { + case WSREP_VAR_INT64: + mysql->value = (char*) &wsrep->value._int64; + mysql->type = SHOW_LONGLONG; + break; + case WSREP_VAR_STRING: + mysql->value = (char*) &wsrep->value._string; + mysql->type = SHOW_CHAR_PTR; + break; + case WSREP_VAR_DOUBLE: + mysql->value = (char*) &wsrep->value._double; + mysql->type = SHOW_DOUBLE; + break; + } +} + +#ifdef OLD_MARIADB int wsrep_show_status (THD *thd, SHOW_VAR *var, char *buff, enum enum_var_type scope) { @@ -750,4 +800,78 @@ int wsrep_show_status (THD *thd, SHOW_VAR *var, char *buff, v->name= 0; // terminator return 0; } +#endif + +#if DYNAMIC +// somehow this mysql status thing works only with statically allocated arrays. +static SHOW_VAR* mysql_status_vars = NULL; +static int mysql_status_len = -1; +#else +static SHOW_VAR mysql_status_vars[512 + 1]; +static const int mysql_status_len = 512; +#endif + +static void export_wsrep_status_to_mysql(THD* thd) +{ + int wsrep_status_len, i; + + wsrep_free_status(thd); + + thd->wsrep_status_vars = wsrep->stats_get(wsrep); + + if (!thd->wsrep_status_vars) { + return; + } + + for (wsrep_status_len = 0; + thd->wsrep_status_vars[wsrep_status_len].name != NULL; + wsrep_status_len++) { + /* */ + } + +#if DYNAMIC + if (wsrep_status_len != mysql_status_len) { + void* tmp = realloc (mysql_status_vars, + (wsrep_status_len + 1) * sizeof(SHOW_VAR)); + if (!tmp) { + + sql_print_error ("Out of memory for wsrep status variables." + "Number of variables: %d", wsrep_status_len); + return; + } + + mysql_status_len = wsrep_status_len; + mysql_status_vars = (SHOW_VAR*)tmp; + } + /* @TODO: fix this: */ +#else + if (mysql_status_len < wsrep_status_len) wsrep_status_len= mysql_status_len; +#endif + + for (i = 0; i < wsrep_status_len; i++) + wsrep_assign_to_mysql (mysql_status_vars + i, thd->wsrep_status_vars + i); + + mysql_status_vars[wsrep_status_len].name = NullS; + mysql_status_vars[wsrep_status_len].value = NullS; + mysql_status_vars[wsrep_status_len].type = SHOW_LONG; +} + +int wsrep_show_status (THD *thd, SHOW_VAR *var, char *buff) +{ + if (WSREP_ON) + { + export_wsrep_status_to_mysql(thd); + var->type= SHOW_ARRAY; + var->value= (char *) &mysql_status_vars; + } + return 0; +} +void wsrep_free_status (THD* thd) +{ + if (thd->wsrep_status_vars) + { + wsrep->stats_free (wsrep, thd->wsrep_status_vars); + thd->wsrep_status_vars = 0; + } +} diff --git a/sql/wsrep_var.h b/sql/wsrep_var.h index 7d3ff50f1d2..8c1d0ddbf51 100644 --- a/sql/wsrep_var.h +++ b/sql/wsrep_var.h @@ -90,10 +90,13 @@ extern bool wsrep_slave_threads_update UPDATE_ARGS; extern bool wsrep_desync_check CHECK_ARGS; extern bool wsrep_desync_update UPDATE_ARGS; -extern bool wsrep_max_ws_size_check CHECK_ARGS; +extern bool wsrep_trx_fragment_size_check CHECK_ARGS; + extern bool wsrep_max_ws_size_update UPDATE_ARGS; extern bool wsrep_reject_queries_update UPDATE_ARGS; +extern bool wsrep_reject_queries_update UPDATE_ARGS; + #else /* WITH_WSREP */ #define WSREP_NONE diff --git a/sql/wsrep_xid.cc b/sql/wsrep_xid.cc index 618c98eade7..e53a3fdeaad 100644 --- a/sql/wsrep_xid.cc +++ b/sql/wsrep_xid.cc @@ -46,8 +46,10 @@ void wsrep_xid_init(XID* xid, const wsrep_uuid_t& uuid, wsrep_seqno_t seqno) int8store(xid->data + WSREP_XID_SEQNO_OFFSET,seqno); } -int wsrep_is_wsrep_xid(const XID* xid) +//int wsrep_is_wsrep_xid(const XID* xid) +int wsrep_is_wsrep_xid(const void* xid_ptr) { + const XID* xid= reinterpret_cast<const XID*>(xid_ptr); return (xid->formatID == 1 && xid->gtrid_length == WSREP_XID_GTRID_LEN && xid->bqual_length == 0 && @@ -114,17 +116,16 @@ static my_bool set_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) return FALSE; } -bool wsrep_set_SE_checkpoint(XID& xid) +void wsrep_set_SE_checkpoint(XID& xid) { - return plugin_foreach(NULL, set_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN, - &xid); + plugin_foreach(NULL, set_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN, &xid); } -bool wsrep_set_SE_checkpoint(const wsrep_uuid_t& uuid, wsrep_seqno_t seqno) +void wsrep_set_SE_checkpoint(const wsrep_uuid_t& uuid, wsrep_seqno_t seqno) { XID xid; wsrep_xid_init(&xid, uuid, seqno); - return wsrep_set_SE_checkpoint(xid); + wsrep_set_SE_checkpoint(xid); } static my_bool get_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) @@ -144,13 +145,13 @@ static my_bool get_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) return FALSE; } -bool wsrep_get_SE_checkpoint(XID& xid) +void wsrep_get_SE_checkpoint(XID& xid) { - return plugin_foreach(NULL, get_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN, + plugin_foreach(NULL, get_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN, &xid); } -bool wsrep_get_SE_checkpoint(wsrep_uuid_t& uuid, wsrep_seqno_t& seqno) +void wsrep_get_SE_checkpoint(wsrep_uuid_t& uuid, wsrep_seqno_t& seqno) { uuid= WSREP_UUID_UNDEFINED; seqno= WSREP_SEQNO_UNDEFINED; @@ -159,24 +160,27 @@ bool wsrep_get_SE_checkpoint(wsrep_uuid_t& uuid, wsrep_seqno_t& seqno) memset(&xid, 0, sizeof(xid)); xid.formatID= -1; - if (wsrep_get_SE_checkpoint(xid)) - { - return true; - } + wsrep_get_SE_checkpoint(xid); - if (xid.formatID == -1) // nil XID - { - return false; - } + if (xid.formatID == -1) return; // nil XID if (!wsrep_is_wsrep_xid(&xid)) { WSREP_WARN("Read non-wsrep XID from storage engines."); - return false; + return; } uuid= *wsrep_xid_uuid(xid); seqno= wsrep_xid_seqno(xid); +} - return false; +void +wsrep_thd_xid(const void *thd_ptr, void *xid, size_t xid_size) +{ + const THD *thd= (const THD*)thd_ptr; + DBUG_ASSERT(xid_size == sizeof(xid_t)); + if (xid_size == sizeof(xid_t)) + { + *(xid_t*) xid = thd->wsrep_xid; + } } diff --git a/sql/wsrep_xid.h b/sql/wsrep_xid.h index 5b33a904de1..04dedb1f583 100644 --- a/sql/wsrep_xid.h +++ b/sql/wsrep_xid.h @@ -15,22 +15,22 @@ #ifndef WSREP_XID_H #define WSREP_XID_H - #include <my_config.h> - + #ifdef WITH_WSREP #include "../wsrep/wsrep_api.h" #include "handler.h" // XID typedef void wsrep_xid_init(xid_t*, const wsrep_uuid_t&, wsrep_seqno_t); +extern "C" int wsrep_is_wsrep_xid(const void* xid); const wsrep_uuid_t* wsrep_xid_uuid(const XID&); wsrep_seqno_t wsrep_xid_seqno(const XID&); -//void wsrep_get_SE_checkpoint(XID&); /* uncomment if needed */ -bool wsrep_get_SE_checkpoint(wsrep_uuid_t&, wsrep_seqno_t&); -//void wsrep_set_SE_checkpoint(XID&); /* uncomment if needed */ -bool wsrep_set_SE_checkpoint(const wsrep_uuid_t&, wsrep_seqno_t); +//void wsrep_get_SE_checkpoint(XID&); uncomment if needed +void wsrep_get_SE_checkpoint(wsrep_uuid_t&, wsrep_seqno_t&); +//void wsrep_set_SE_checkpoint(XID&); uncomment if needed +void wsrep_set_SE_checkpoint(const wsrep_uuid_t&, wsrep_seqno_t); #endif /* WITH_WSREP */ #endif /* WSREP_UTILS_H */ diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index a0c4baad64d..bc96e91c486 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -44,8 +44,8 @@ Created April 08, 2011 Vasil Dimov #include <algorithm> -#include "mysql/service_wsrep.h" /* wsrep_recovery */ #include <my_service_manager.h> +#include "mysql/service_wsrep.h" /* wsrep_recovery */ enum status_severity { STATUS_INFO, @@ -824,7 +824,7 @@ DECLARE_THREAD(buf_dump_thread)(void*) if (srv_buffer_pool_load_at_startup) { #ifdef WITH_WSREP - if (!wsrep_recovery) { + if (!get_wsrep_recovery()) { #endif /* WITH_WSREP */ buf_load(); #ifdef WITH_WSREP @@ -858,7 +858,7 @@ DECLARE_THREAD(buf_dump_thread)(void*) "Dumping of buffer pool not started" " as load was incomplete"); #ifdef WITH_WSREP - } else if (wsrep_recovery) { + } else if (get_wsrep_recovery()) { #endif /* WITH_WSREP */ } else { buf_dump(FALSE/* do complete dump at shutdown */); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index b0af34814af..56d41bf00b6 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -153,13 +153,11 @@ void close_thread_tables(THD* thd); extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log; static inline wsrep_ws_handle_t* -wsrep_ws_handle(THD* thd, const trx_t* trx) { +wsrep_ws_handle(THD* thd) { return wsrep_ws_handle_for_trx(wsrep_thd_ws_handle(thd), - (wsrep_trx_id_t)trx->id); + wsrep_thd_next_trx_id(thd)); } -extern TC_LOG* tc_log; -extern void wsrep_cleanup_transaction(THD *thd); static int wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, my_bool signal); @@ -167,6 +165,15 @@ static void wsrep_fake_trx_id(handlerton* hton, THD *thd); static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid); static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid); + +extern bool wsrep_prepare_key_for_innodb( + THD* thd, + const uchar *cache_key, + size_t cache_key_len, + const uchar* row_id, + size_t row_id_len, + wsrep_buf_t* key, + size_t* key_len); #endif /* WITH_WSREP */ /** to protect innobase_open_files */ @@ -4658,6 +4665,14 @@ innobase_commit( this one, to allow then to group commit with us. */ thd_wakeup_subsequent_commits(thd, 0); +#ifdef WITH_WSREP + /* Serialisation history has been written, so the + commit is now ordered. */ + if (trx->mysql_thd) { + (void)wsrep_ordered_commit_if_no_binlog(trx->mysql_thd); + } +#endif /* WITH_WSREP */ + /* Now do a write + flush of logs. */ trx_commit_complete_for_mysql(trx); @@ -5137,7 +5152,8 @@ static void innobase_kill_query(handlerton*, THD* thd, enum thd_kill_levels) { DBUG_ENTER("innobase_kill_query"); #ifdef WITH_WSREP - if (wsrep_thd_get_conflict_state(thd) != NO_CONFLICT) { + if (wsrep_on(thd) && + wsrep_thd_get_conflict_state(thd) != NO_CONFLICT) { /* if victim has been signaled by BF thread and/or aborting is already progressing, following query aborting is not necessary any more. @@ -6636,7 +6652,6 @@ ha_innobase::close() UNIV_INTERN ulint wsrep_innobase_mysql_sort( -/*======================*/ /* out: str contains sort string */ int mysql_type, /* in: MySQL type */ uint charset_number, /* in: number of the charset */ @@ -7060,7 +7075,6 @@ Stores a key value for a row to a buffer. UNIV_INTERN uint wsrep_store_key_val_for_row( -/*=========================*/ THD* thd, TABLE* table, uint keynr, /*!< in: key number */ @@ -7072,7 +7086,8 @@ wsrep_store_key_val_for_row( { KEY* key_info = table->key_info + keynr; KEY_PART_INFO* key_part = key_info->key_part; - KEY_PART_INFO* end = key_part + key_info->user_defined_key_parts; + KEY_PART_INFO* end = + key_part + key_info->user_defined_key_parts; char* buff_start = buff; enum_field_types mysql_type; Field* field; @@ -8779,7 +8794,6 @@ calc_row_difference( static int wsrep_calc_row_hash( -/*================*/ byte* digest, /*!< in/out: md5 sum */ const uchar* row, /*!< in: row in MySQL format */ TABLE* table, /*!< in: table in MySQL data @@ -10310,7 +10324,6 @@ wsrep_dict_foreign_find_index( extern dberr_t wsrep_append_foreign_key( -/*===========================*/ trx_t* trx, /*!< in: trx */ dict_foreign_t* foreign, /*!< in: foreign key constraint */ const rec_t* rec, /*!<in: clustered index record */ @@ -10455,7 +10468,8 @@ wsrep_append_foreign_key( wsrep_buf_t wkey_part[3]; wsrep_key_t wkey = {wkey_part, 3}; - if (!wsrep_prepare_key( + if (!wsrep_prepare_key_for_innodb( + thd, (const uchar*)cache_key, cache_key_len + 1, (const uchar*)key, len+1, @@ -10471,7 +10485,7 @@ wsrep_append_foreign_key( rcode = (int)wsrep->append_key( wsrep, - wsrep_ws_handle(thd, trx), + wsrep_ws_handle(thd), &wkey, 1, shared ? WSREP_KEY_SHARED : WSREP_KEY_EXCLUSIVE, @@ -10491,7 +10505,6 @@ wsrep_append_foreign_key( static int wsrep_append_key( -/*=============*/ THD *thd, trx_t *trx, TABLE_SHARE *table_share, @@ -10502,6 +10515,9 @@ wsrep_append_key( { DBUG_ENTER("wsrep_append_key"); bool const copy = true; + DBUG_PRINT("enter", + ("thd: %lld trx: %lld", wsrep_thd_thread_id(thd), + (long long)trx->id)); #ifdef WSREP_DEBUG_PRINT fprintf(stderr, "%s conn %ld, trx %llu, keylen %d, table %s\n Query: %s ", (shared) ? "Shared" : "Exclusive", @@ -10515,7 +10531,8 @@ wsrep_append_key( wsrep_buf_t wkey_part[3]; wsrep_key_t wkey = {wkey_part, 3}; - if (!wsrep_prepare_key( + if (!wsrep_prepare_key_for_innodb( + thd, (const uchar*)table_share->table_cache_key.str, table_share->table_cache_key.length, (const uchar*)key, key_len, @@ -10531,7 +10548,7 @@ wsrep_append_key( int rcode = (int)wsrep->append_key( wsrep, - wsrep_ws_handle(thd, trx), + wsrep_ws_handle(thd), &wkey, 1, shared ? WSREP_KEY_SHARED : WSREP_KEY_EXCLUSIVE, @@ -10574,7 +10591,6 @@ referenced_by_foreign_key2( int ha_innobase::wsrep_append_keys( -/*===========================*/ THD *thd, bool shared, const uchar* record0, /* in: row in MySQL format */ @@ -10664,12 +10680,10 @@ ha_innobase::wsrep_append_keys( thd, trx, table_share, keyval0, len+1, shared); - if (rcode) { - DBUG_RETURN(rcode); - } + if (rcode) DBUG_RETURN(rcode); - if (key_info->flags & HA_NOSAME || shared) - key_appended = true; + if (key_info->flags & HA_NOSAME || shared) + key_appended = true; } else { WSREP_DEBUG("NULL key skipped: %s", wsrep_thd_query(thd)); @@ -16754,7 +16768,10 @@ ha_innobase::get_auto_increment( thd_get_thread_id(ha_thd()), current, autoinc); - if (!wsrep_on(ha_thd())) { +#ifdef WITH_WSREP + if (!wsrep_on(ha_thd())) +#endif + { current = autoinc - m_prebuilt->autoinc_increment; } @@ -18793,8 +18810,13 @@ wsrep_innobase_kill_one_trx( DBUG_RETURN(1); } + if (wsrep_thd_trx_id(thd) == WSREP_UNDEFINED_TRX_ID) { + wsrep_ws_handle(thd); + } + WSREP_LOG_CONFLICT(bf_thd, thd, TRUE); + wsrep_thd_LOCK(thd); WSREP_DEBUG("BF kill (" ULINTPF ", seqno: " INT64PF "), victim: (%lu) trx: " TRX_ID_FMT, signal, bf_seqno, @@ -18806,104 +18828,8 @@ wsrep_innobase_kill_one_trx( wsrep_thd_conflict_state(thd, FALSE), wsrep_thd_ws_handle(thd)->trx_id); - wsrep_thd_LOCK(thd); - DBUG_EXECUTE_IF("sync.wsrep_after_BF_victim_lock", - { - const char act[]= - "now " - "wait_for signal.wsrep_after_BF_victim_lock"; - DBUG_ASSERT(!debug_sync_set_action(bf_thd, - STRING_WITH_LEN(act))); - };); - - - if (wsrep_thd_query_state(thd) == QUERY_EXITING) { - WSREP_DEBUG("kill trx EXITING for " TRX_ID_FMT, - victim_trx->id); - wsrep_thd_UNLOCK(thd); - DBUG_RETURN(0); - } - - if (wsrep_thd_exec_mode(thd) != LOCAL_STATE) { - WSREP_DEBUG("withdraw for BF trx: " TRX_ID_FMT ", state: %d", - victim_trx->id, - wsrep_thd_get_conflict_state(thd)); - } - - switch (wsrep_thd_get_conflict_state(thd)) { - case NO_CONFLICT: - wsrep_thd_set_conflict_state(thd, MUST_ABORT); - break; - case MUST_ABORT: - WSREP_DEBUG("victim " TRX_ID_FMT " in MUST ABORT state", - victim_trx->id); - wsrep_thd_UNLOCK(thd); - wsrep_thd_awake(thd, signal); - DBUG_RETURN(0); - break; - case ABORTED: - case ABORTING: // fall through - default: - WSREP_DEBUG("victim " TRX_ID_FMT " in state %d", - victim_trx->id, wsrep_thd_get_conflict_state(thd)); - wsrep_thd_UNLOCK(thd); - DBUG_RETURN(0); - break; - } - - switch (wsrep_thd_query_state(thd)) { - case QUERY_COMMITTING: - enum wsrep_status rcode; - - WSREP_DEBUG("kill query for: %ld", - thd_get_thread_id(thd)); - WSREP_DEBUG("kill trx QUERY_COMMITTING for " TRX_ID_FMT, - victim_trx->id); - - if (wsrep_thd_exec_mode(thd) == REPL_RECV) { - wsrep_abort_slave_trx(bf_seqno, - wsrep_thd_trx_seqno(thd)); - } else { - wsrep_t *wsrep= get_wsrep(); - rcode = wsrep->abort_pre_commit( - wsrep, bf_seqno, - (wsrep_trx_id_t)wsrep_thd_ws_handle(thd)->trx_id - ); - - switch (rcode) { - case WSREP_WARNING: - WSREP_DEBUG("cancel commit warning: " - TRX_ID_FMT, - victim_trx->id); - wsrep_thd_UNLOCK(thd); - wsrep_thd_awake(thd, signal); - DBUG_RETURN(1); - break; - case WSREP_OK: - break; - default: - WSREP_ERROR( - "cancel commit bad exit: %d " - TRX_ID_FMT, - rcode, victim_trx->id); - /* unable to interrupt, must abort */ - /* note: kill_mysql() will block, if we cannot. - * kill the lock holder first. - */ - abort(); - break; - } - } - wsrep_thd_UNLOCK(thd); - wsrep_thd_awake(thd, signal); - break; - case QUERY_EXEC: - /* it is possible that victim trx is itself waiting for some - * other lock. We need to cancel this waiting - */ - WSREP_DEBUG("kill trx QUERY_EXEC for " TRX_ID_FMT, - victim_trx->id); - + if (wsrep_bf_abort(bf_thd, thd, signal)) + { victim_trx->lock.was_chosen_as_deadlock_victim= TRUE; if (victim_trx->lock.wait_lock) { @@ -18916,9 +18842,8 @@ wsrep_innobase_kill_one_trx( victim_trx->lock.was_chosen_as_deadlock_victim= TRUE; lock_cancel_waiting_and_release(wait_lock); } - wsrep_thd_UNLOCK(thd); - wsrep_thd_awake(thd, signal); + wsrep_thd_awake(thd, signal); } else { /* abort currently executing query */ DBUG_PRINT("wsrep",("sending KILL_QUERY to: %lu", @@ -18936,47 +18861,10 @@ wsrep_innobase_kill_one_trx( wsrep_thd_trx_seqno(thd)); } } - break; - case QUERY_IDLE: - { - WSREP_DEBUG("kill IDLE for " TRX_ID_FMT, victim_trx->id); - - if (wsrep_thd_exec_mode(thd) == REPL_RECV) { - WSREP_DEBUG("kill BF IDLE, seqno: %lld", - (long long)wsrep_thd_trx_seqno(thd)); - wsrep_thd_UNLOCK(thd); - wsrep_abort_slave_trx(bf_seqno, - wsrep_thd_trx_seqno(thd)); - DBUG_RETURN(0); - } - /* This will lock thd from proceeding after net_read() */ - wsrep_thd_set_conflict_state(thd, ABORTING); - - wsrep_lock_rollback(); - - if (wsrep_aborting_thd_contains(thd)) { - WSREP_WARN("duplicate thd aborter %lu", - (ulong) thd_get_thread_id(thd)); - } else { - wsrep_aborting_thd_enqueue(thd); - DBUG_PRINT("wsrep",("enqueuing trx abort for %lu", - thd_get_thread_id(thd))); - WSREP_DEBUG("enqueuing trx abort for (%lu)", - thd_get_thread_id(thd)); - } - - DBUG_PRINT("wsrep",("signalling wsrep rollbacker")); - WSREP_DEBUG("signaling aborter"); - wsrep_unlock_rollback(); - wsrep_thd_UNLOCK(thd); - - break; } - default: - WSREP_WARN("bad wsrep query state: %d", - wsrep_thd_query_state(thd)); + else + { wsrep_thd_UNLOCK(thd); - break; } DBUG_RETURN(0); @@ -18995,11 +18883,25 @@ wsrep_abort_transaction( trx_t* victim_trx = thd_to_trx(victim_thd); trx_t* bf_trx = (bf_thd) ? thd_to_trx(bf_thd) : NULL; + if (wsrep_debug) + { + wsrep_thd_LOCK(victim_thd); + WSREP_DEBUG("abort transaction: BF: %s victim: %s conf: %d", + wsrep_thd_query(bf_thd), + wsrep_thd_query(victim_thd), + wsrep_thd_conflict_state(victim_thd, FALSE)); + wsrep_thd_UNLOCK(victim_thd); + } - WSREP_DEBUG("abort transaction: BF: %s victim: %s victim conf: %d", + if (wsrep_debug) + { + wsrep_thd_LOCK(victim_thd); + WSREP_DEBUG("abort transaction: BF: %s victim: %s conf: %d", wsrep_thd_query(bf_thd), wsrep_thd_query(victim_thd), - wsrep_thd_conflict_state(victim_thd, FALSE)); + wsrep_thd_get_conflict_state(victim_thd)); + wsrep_thd_UNLOCK(victim_thd); + } if (victim_trx) { lock_mutex_enter(); diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index f2bb8aa5ef2..dc13b8d82ca 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -599,11 +599,9 @@ thd_get_work_part_info( struct trx_t; #ifdef WITH_WSREP #include <mysql/service_wsrep.h> -//extern "C" int wsrep_trx_order_before(void *thd1, void *thd2); - +#ifdef OUT extern "C" bool wsrep_thd_is_wsrep_on(THD *thd); - extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode); extern "C" void wsrep_thd_set_query_state( THD *thd, enum wsrep_query_state state); @@ -616,6 +614,7 @@ extern "C" query_id_t wsrep_thd_query_id(THD *thd); extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd); extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id); #endif +#endif extern const struct _ft_vft ft_vft_result; @@ -660,10 +659,6 @@ innobase_index_name_is_reserved( be created. */ MY_ATTRIBUTE((nonnull(1), warn_unused_result)); -#ifdef WITH_WSREP -//extern "C" int wsrep_trx_is_aborting(void *thd_ptr); -#endif - /** Parse hint for table and its indexes, and update the information in dictionary. @param[in] thd Connection thread diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index 1313705f119..28bc8f9e565 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -240,6 +240,11 @@ wsrep_innobase_kill_one_trx(void * const thd_ptr, ulint wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, unsigned char* str, unsigned int str_length, unsigned int buf_length); +my_bool wsrep_thd_is_SR(void *thd_ptr); +my_bool wsrep_thd_skip_locking(void *thd_ptr); +void wsrep_handle_SR_rollback(void *BF_thd_ptr, void *victim_thd_ptr); +extern "C" void wsrep_thd_xid(const void *thd_ptr, void *xid, size_t xid_size); +bool wsrep_bf_abort(void *bf_thd_ptr, void *victim_thd_ptr, bool signal); #endif /* WITH_WSREP */ /**********************************************************************//** diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 76d4e9caba0..114a2f8f349 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -270,6 +270,23 @@ trx_commit_step( /*============*/ que_thr_t* thr); /*!< in: query thread */ +#ifdef WITH_WSREP +/**********************************************************************//** +Prints info about a transaction. +Transaction information may be retrieved without having trx_sys->mutex acquired +so it may not be completely accurate. The caller must own lock_sys->mutex +and the trx must have some locks to make sure that it does not escape +without locking lock_sys->mutex. */ +UNIV_INTERN +void +wsrep_trx_print_locking( +/*==============*/ + FILE* f, /*!< in: output stream */ + const trx_t* trx, /*!< in: transaction */ + ulint max_query_len) /*!< in: max query length to print, + or 0 to use the default max length */ + MY_ATTRIBUTE((nonnull)); +#endif /* WITH_WSREP */ /**********************************************************************//** Prints info about a transaction. Caller must hold trx_sys.mutex. */ diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 4d93f2c449c..8669c7345bb 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -778,9 +778,7 @@ lock_rec_has_to_wait( << wsrep_thd_query(lock2->trx->mysql_thd); } - if (wsrep_trx_order_before(trx->mysql_thd, - lock2->trx->mysql_thd) - && (type_mode & LOCK_MODE_MASK) == LOCK_X + if ((type_mode & LOCK_MODE_MASK) == LOCK_X && (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X) { if (for_locking || wsrep_debug) { /* exclusive lock conflicts are not @@ -1115,11 +1113,14 @@ wsrep_kill_victim( } my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE); + if (!bf_this) return; + my_bool bf_other = wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE); if ((bf_this && !bf_other) || - (bf_this && bf_other && wsrep_trx_order_before( - trx->mysql_thd, lock->trx->mysql_thd))) { +// (bf_this && bf_other && wsrep_trx_order_before( +// trx->mysql_thd, lock->trx->mysql_thd))) { + (bf_this)) { if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) { if (wsrep_debug) { @@ -7005,6 +7006,9 @@ DeadlockChecker::trx_rollback() trx_t* trx = m_wait_lock->trx; print("*** WE ROLL BACK TRANSACTION (1)\n"); +#ifdef WITH_WSREP + wsrep_handle_SR_rollback(m_start->mysql_thd, trx->mysql_thd); +#endif trx_mutex_enter(trx); diff --git a/storage/innobase/lock/lock0wait.cc b/storage/innobase/lock/lock0wait.cc index 4a3adaa4757..955ce8c7b8f 100644 --- a/storage/innobase/lock/lock0wait.cc +++ b/storage/innobase/lock/lock0wait.cc @@ -195,8 +195,8 @@ wsrep_is_BF_lock_timeout( if (wsrep_on_trx(trx) && wsrep_thd_is_BF(trx->mysql_thd, FALSE) && trx->error_state != DB_DEADLOCK) { - ib::info() << "WSREP: BF lock wait long for trx:" << ib::hex(trx->id) - << " query: " << wsrep_thd_query(trx->mysql_thd); + ib::info() << "WSREP: BF lock wait long for trx:" << ib::hex(trx->id) + << " query: " << wsrep_thd_query(trx->mysql_thd); if (!locked) { lock_mutex_enter(); } @@ -214,7 +214,9 @@ wsrep_is_BF_lock_timeout( os_event_set(srv_monitor_event); return true; } - return false; + + + return false; } #endif /* WITH_WSREP */ diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 37ae828d09d..96db940e769 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -50,6 +50,11 @@ Created 4/20/1996 Heikki Tuuri #include "fts0types.h" #include "m_string.h" #include "gis0geo.h" +#include "log.h" +#include "wsrep_mysqld.h" +#ifdef WITH_WSREP +#include "wsrep_schema.h" +#endif /************************************************************************* IMPORTANT NOTE: Any operation that generates redo MUST check that there @@ -3240,9 +3245,26 @@ row_ins_clust_index_entry( n_uniq = dict_index_is_unique(index) ? index->n_uniq : 0; +#ifdef WITH_WSREP + const bool skip_locking + = wsrep_thd_skip_locking(thr_get_trx(thr)->mysql_thd); + ulint flags = skip_locking | index->table->is_temporary() + ? BTR_NO_LOCKING_FLAG + : index->table->no_rollback() ? BTR_NO_ROLLBACK : 0; +#ifdef UNIV_DEBUG + if (skip_locking && sr_table_name_full_str != index->table->name.m_name) { + WSREP_ERROR("Record locking is disabled in this thread, " + "but the table being modified is not " + "`%s`: `%s`.", sr_table_name_full_str.c_str(), + index->table->name.m_name); + ut_error; + } +#endif /* UNIV_DEBUG */ +#else ulint flags = index->table->no_rollback() ? BTR_NO_ROLLBACK : index->table->is_temporary() ? BTR_NO_LOCKING_FLAG : 0; +#endif /* WITH_WSREP */ const ulint orig_n_fields = entry->n_fields; /* Try first optimistic descent to the B-tree */ diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index b68efbfa7be..fe49d298bbc 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -56,6 +56,15 @@ Created 12/19/1997 Heikki Tuuri #include "ha_prototypes.h" #include "srv0mon.h" #include "ut0new.h" +#include "m_string.h" /* for my_sys.h */ +#include "my_sys.h" /* DEBUG_SYNC_C */ +#ifdef WITH_WSREP +#include "wsrep_schema.h" +#endif +#include "my_compare.h" /* enum icp_result */ +#include "thr_lock.h" +#include "handler.h" +#include "ha_innodb.h" /* Maximum number of rows to prefetch; MySQL interface has another parameter */ #define SEL_MAX_N_PREFETCH 16 @@ -4503,6 +4512,13 @@ row_search_mvcc( set_also_gap_locks = FALSE; } +#ifdef WITH_WSREP + if (wsrep_thd_skip_locking(trx->mysql_thd)) { + + ut_ad(sr_table_name_full_str == prebuilt->table->name.m_name); + set_also_gap_locks = FALSE; + } +#endif /* WITH_WSREP */ /* Note that if the search mode was GE or G, then the cursor naturally moves upward (in fetch next) in alphabetical order, diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 447132dcf86..ab15601d001 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -2450,6 +2450,10 @@ row_upd_sec_index_entry( row_ins_sec_index_entry() below */ if (!rec_get_deleted_flag( rec, dict_table_is_comp(index->table))) { +#ifdef WITH_WSREP + const upd_node_t* parent = + static_cast<const upd_node_t*>(node->common.parent); +#endif /* WITH_WSREP */ err = btr_cur_del_mark_set_sec_rec( flags, btr_cur, TRUE, thr, &mtr); if (err != DB_SUCCESS) { @@ -2457,8 +2461,11 @@ row_upd_sec_index_entry( } #ifdef WITH_WSREP if (!referenced && foreign - && wsrep_must_process_fk(node, trx) - && !wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { + && wsrep_on(trx->mysql_thd) + && !wsrep_thd_is_BF(trx->mysql_thd, FALSE) + && (!parent || que_node_get_type(parent) != QUE_NODE_UPDATE || + !parent->cascade_node) + ) { ulint* offsets = rec_get_offsets( rec, index, NULL, true, @@ -2997,7 +3004,8 @@ row_upd_del_mark_clust_rec( err = row_upd_check_references_constraints( node, pcur, index->table, index, offsets, thr, mtr); #ifdef WITH_WSREP - } else if (foreign && wsrep_must_process_fk(node, trx)) { + } else if (trx && wsrep_on(trx->mysql_thd) && err == DB_SUCCESS + && wsrep_must_process_fk(node, trx)) { err = wsrep_row_upd_check_foreign_constraints( node, pcur, index->table, index, offsets, thr, mtr); diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index c0864e40622..048d06d2835 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -186,6 +186,11 @@ trx_rollback_to_savepoint( partial rollback requested, or NULL for complete rollback */ { +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && savept == NULL) { + wsrep_handle_SR_rollback(NULL, trx->mysql_thd); + } +#endif /* WITH_WSREP */ ut_ad(!trx_mutex_own(trx)); trx_start_if_not_started_xa(trx, true); diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc index 81ad85dca7d..12bbd8be1e7 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -61,7 +61,8 @@ trx_rseg_update_wsrep_checkpoint( long long xid_seqno = wsrep_xid_seqno(xid); const byte* xid_uuid = wsrep_xid_uuid(xid); - if (!memcmp(xid_uuid, wsrep_uuid, sizeof wsrep_uuid)) { + if (!memcmp(xid_uuid, wsrep_uuid, sizeof wsrep_uuid) && + xid_seqno != -1) { ut_ad(xid_seqno > wsrep_seqno); } else { memcpy(wsrep_uuid, xid_uuid, sizeof wsrep_uuid); diff --git a/wsrep/wsrep_api.h b/wsrep/wsrep_api.h index 1d6bc059d3d..0923507a1db 100644 --- a/wsrep/wsrep_api.h +++ b/wsrep/wsrep_api.h @@ -48,6 +48,7 @@ #define WSREP_H #include <stdint.h> +#include <stdbool.h> #include <stdlib.h> #include <unistd.h> #include <time.h> @@ -62,7 +63,7 @@ extern "C" { * * **************************************************************************/ -#define WSREP_INTERFACE_VERSION "25" +#define WSREP_INTERFACE_VERSION "26" /*! Empty backend spec */ #define WSREP_NONE "none" @@ -110,27 +111,40 @@ typedef void (*wsrep_log_cb_t)(wsrep_log_level_t, const char *); #define WSREP_CAP_UNORDERED ( 1ULL << 12 ) #define WSREP_CAP_ANNOTATION ( 1ULL << 13 ) #define WSREP_CAP_PREORDERED ( 1ULL << 14 ) +#define WSREP_CAP_STREAMING ( 1ULL << 15 ) +#define WSREP_CAP_SNAPSHOT ( 1ULL << 16 ) +#define WSREP_CAP_NBO ( 1ULL << 17 ) +typedef uint32_t wsrep_cap_t; //!< capabilities bitmask /*! - * Writeset flags + * Writeset flags * - * COMMIT the writeset and all preceding writesets must be committed + * TRX_END the writeset and all preceding writesets must be committed * ROLLBACK all preceding writesets in a transaction must be rolled back * ISOLATION the writeset must be applied AND committed in isolation * PA_UNSAFE the writeset cannot be applied in parallel * COMMUTATIVE the order in which the writeset is applied does not matter * NATIVE the writeset contains another writeset in this provider format * - * Note that some of the flags are mutually exclusive (e.g. COMMIT and + * TRX_START shall be set on the first trx fragment by provider + * TRX_PREPARE shall be set on the fragment which prepares the transaction + * + * Note that some of the flags are mutually exclusive (e.g. TRX_END and * ROLLBACK). */ -#define WSREP_FLAG_COMMIT ( 1ULL << 0 ) +#define WSREP_FLAG_TRX_END ( 1ULL << 0 ) #define WSREP_FLAG_ROLLBACK ( 1ULL << 1 ) #define WSREP_FLAG_ISOLATION ( 1ULL << 2 ) #define WSREP_FLAG_PA_UNSAFE ( 1ULL << 3 ) #define WSREP_FLAG_COMMUTATIVE ( 1ULL << 4 ) #define WSREP_FLAG_NATIVE ( 1ULL << 5 ) +#define WSREP_FLAG_TRX_START ( 1ULL << 6 ) +#define WSREP_FLAG_TRX_PREPARE ( 1ULL << 7 ) +#define WSREP_FLAG_SNAPSHOT ( 1ULL << 8 ) + +#define WSREP_FLAGS_LAST WSREP_FLAG_SNAPSHOT +#define WSREP_FLAGS_MASK ((WSREP_FLAGS_LAST << 1) - 1) typedef uint64_t wsrep_trx_id_t; //!< application transaction ID @@ -158,7 +172,8 @@ typedef enum wsrep_status WSREP_CONN_FAIL, //!< error in client connection, must abort WSREP_NODE_FAIL, //!< error in node state, wsrep must reinit WSREP_FATAL, //!< fatal error, server must abort - WSREP_NOT_IMPLEMENTED //!< feature not implemented + WSREP_NOT_IMPLEMENTED, //!< feature not implemented + WSREP_NOT_ALLOWED //!< operation not allowed } wsrep_status_t; @@ -178,8 +193,9 @@ typedef enum wsrep_cb_status /*! * UUID type - for all unique IDs */ -typedef struct wsrep_uuid { +typedef union wsrep_uuid { uint8_t data[16]; + size_t alignment; } wsrep_uuid_t; /*! Undefined UUID */ @@ -202,6 +218,18 @@ wsrep_uuid_scan (const char* str, size_t str_len, wsrep_uuid_t* uuid); extern int wsrep_uuid_print (const wsrep_uuid_t* uuid, char* str, size_t str_len); +/*! + * @brief Compare two UUIDs + * + * Performs a byte by byte comparison of lhs and rhs. + * Returns 0 if lhs and rhs match, otherwise -1 or 1 according to the + * difference of the first byte that differs in lsh and rhs. + * + * @return -1, 0, 1 if lhs is respectively smaller, equal, or greater than rhs + */ +extern int +wsrep_uuid_compare (const wsrep_uuid_t* lhs, const wsrep_uuid_t* rhs); + #define WSREP_MEMBER_NAME_LEN 32 //!< maximum logical member name length #define WSREP_INCOMING_LEN 256 //!< max Domain Name length + 0x00 @@ -237,6 +265,14 @@ wsrep_gtid_scan(const char* str, size_t str_len, wsrep_gtid_t* gtid); extern int wsrep_gtid_print(const wsrep_gtid_t* gtid, char* str, size_t str_len); +/*! + * Source/server transaction ID (trx ID assigned at originating node) + */ +typedef struct wsrep_stid { + wsrep_uuid_t node; //!< source node ID + wsrep_trx_id_t trx; //!< local trx ID at source + wsrep_conn_id_t conn; //!< local connection ID at source +} wsrep_stid_t; /*! * Transaction meta data @@ -244,10 +280,24 @@ wsrep_gtid_print(const wsrep_gtid_t* gtid, char* str, size_t str_len); typedef struct wsrep_trx_meta { wsrep_gtid_t gtid; /*!< Global transaction identifier */ - wsrep_seqno_t depends_on; /*!< Sequence number part of the last transaction - this transaction depends on */ + wsrep_stid_t stid; /*!< Source transaction identifier */ + wsrep_seqno_t depends_on; /*!< Sequence number of the last transaction + this transaction may depend on */ } wsrep_trx_meta_t; +/*! Abstract data buffer structure */ +typedef struct wsrep_buf +{ + const void* ptr; /*!< Pointer to data buffer */ + size_t len; /*!< Length of buffer */ +} wsrep_buf_t; + +/*! Transaction handle struct passed for wsrep transaction handling calls */ +typedef struct wsrep_ws_handle +{ + wsrep_trx_id_t trx_id; //!< transaction ID + void* opaque; //!< opaque provider transaction context data +} wsrep_ws_handle_t; /*! * member status @@ -288,17 +338,53 @@ typedef struct wsrep_view_info { wsrep_gtid_t state_id; //!< global state ID wsrep_seqno_t view; //!< global view number wsrep_view_status_t status; //!< view status - wsrep_bool_t state_gap; //!< gap between global and local states + wsrep_cap_t capabilities;//!< capabilities available in the view int my_idx; //!< index of this member in the view int memb_num; //!< number of members in the view int proto_ver; //!< application protocol agreed on the view wsrep_member_info_t members[1];//!< array of member information } wsrep_view_info_t; + +/*! + * @brief connected to group + * + * This handler is called once the first primary view is seen. + * The purpose of this call is to provide basic information only, + * like node UUID and group UUID. + */ +typedef enum wsrep_cb_status (*wsrep_connected_cb_t) ( + void* app_ctx, + const wsrep_view_info_t* view +); + + +/*! + * @brief group view handler + * + * This handler is called in *total order* corresponding to the group + * configuration change. It is to provide a vital information about + * new group view. + * + * @param app_ctx application context + * @param recv_ctx receiver context + * @param view new view on the group + * @param state current state + * @param state_len length of current state + */ +typedef enum wsrep_cb_status (*wsrep_view_cb_t) ( + void* app_ctx, + void* recv_ctx, + const wsrep_view_info_t* view, + const char* state, + size_t state_len +); + + /*! * Magic string to tell provider to engage into trivial (empty) state transfer. * No data will be passed, but the node shall be considered JOINED. - * Should be passed in sst_req parameter of wsrep_view_cb_t. + * Should be passed in sst_req parameter of wsrep_sst_cb_t. */ #define WSREP_STATE_TRANSFER_TRIVIAL "trivial" @@ -306,40 +392,39 @@ typedef struct wsrep_view_info { * Magic string to tell provider not to engage in state transfer at all. * The member will stay in WSREP_MEMBER_UNDEFINED state but will keep on * receiving all writesets. - * Should be passed in sst_req parameter of wsrep_view_cb_t. + * Should be passed in sst_req parameter of wsrep_sst_cb_t. */ #define WSREP_STATE_TRANSFER_NONE "none" + /*! - * @brief group view handler + * @brief Creates and returns State Snapshot Transfer request for provider. * - * This handler is called in total order corresponding to the group - * configuration change. It is to provide a vital information about - * new group view. If view info indicates existence of discontinuity - * between group and member states, state transfer request message - * should be filled in by the callback implementation. + * This handler is called whenever the node is found to miss some of events + * from the cluster history (e.g. fresh node joining the cluster). + * SST will be used if it is impossible (or impractically long) to replay + * missing events, which may be not known in advance, so the node must always + * be ready to accept full SST or abort in case event replay is impossible. + * + * Normally SST request is an opaque buffer that is passed to the + * chosen SST donor node and must contain information sufficient for + * donor to deliver SST (typically SST method and delivery address). + * See above macros WSREP_STATE_TRANSFER_TRIVIAL and WSREP_STATE_TRANSFER_NONE + * to modify the standard provider behavior. * * @note Currently it is assumed that sst_req is allocated using * malloc()/calloc()/realloc() and it will be freed by - * wsrep implementation. + * wsrep provider. * * @param app_ctx application context - * @param recv_ctx receiver context - * @param view new view on the group - * @param state current state - * @param state_len lenght of current state * @param sst_req location to store SST request * @param sst_req_len location to store SST request length or error code, * value of 0 means no SST. */ -typedef enum wsrep_cb_status (*wsrep_view_cb_t) ( - void* app_ctx, - void* recv_ctx, - const wsrep_view_info_t* view, - const char* state, - size_t state_len, - void** sst_req, - size_t* sst_req_len +typedef enum wsrep_cb_status (*wsrep_sst_request_cb_t) ( + void* app_ctx, + void** sst_req, + size_t* sst_req_len ); @@ -349,47 +434,24 @@ typedef enum wsrep_cb_status (*wsrep_view_cb_t) ( * This handler is called from wsrep library to apply replicated writeset * Must support brute force applying for multi-master operation * - * @param recv_ctx receiver context pointer provided by the application - * @param data data buffer containing the writeset - * @param size data buffer size - * @param flags WSREP_FLAG_... flags - * @param meta transaction meta data of the writeset to be applied + * @param recv_ctx receiver context pointer provided by the application + * @param ws_handle internal provider writeset handle + * @param flags WSREP_FLAG_... flags + * @param data data buffer containing the writeset + * @param meta transaction meta data of the writeset to be applied + * @param exit_loop set to true to exit receive loop * - * @return success code: - * @retval WSREP_OK - * @retval WSREP_NOT_IMPLEMENTED appl. does not support the writeset format - * @retval WSREP_ERROR failed to apply the writeset + * @return error code: + * @retval 0 - success + * @retval non-0 - application-specific error code */ typedef enum wsrep_cb_status (*wsrep_apply_cb_t) ( - void* recv_ctx, - const void* data, - size_t size, - uint32_t flags, - const wsrep_trx_meta_t* meta -); - - -/*! - * @brief commit callback - * - * This handler is called to commit the changes made by apply callback. - * - * @param recv_ctx receiver context pointer provided by the application - * @param flags WSREP_FLAG_... flags - * @param meta transaction meta data of the writeset to be committed - * @param exit set to true to exit recv loop - * @param commit true - commit writeset, false - rollback writeset - * - * @return success code: - * @retval WSREP_OK - * @retval WSREP_ERROR call failed - */ -typedef enum wsrep_cb_status (*wsrep_commit_cb_t) ( - void* recv_ctx, - uint32_t flags, - const wsrep_trx_meta_t* meta, - wsrep_bool_t* exit, - wsrep_bool_t commit + void* recv_ctx, + const wsrep_ws_handle_t* ws_handle, + uint32_t flags, + const wsrep_buf_t* data, + const wsrep_trx_meta_t* meta, + wsrep_bool_t* exit_loop ); @@ -401,12 +463,10 @@ typedef enum wsrep_cb_status (*wsrep_commit_cb_t) ( * * @param recv_ctx receiver context pointer provided by the application * @param data data buffer containing the writeset - * @param size data buffer size */ typedef enum wsrep_cb_status (*wsrep_unordered_cb_t) ( - void* recv_ctx, - const void* data, - size_t size + void* recv_ctx, + const wsrep_buf_t* data ); @@ -421,21 +481,17 @@ typedef enum wsrep_cb_status (*wsrep_unordered_cb_t) ( * * @param app_ctx application context * @param recv_ctx receiver context - * @param msg state transfer request message - * @param msg_len state transfer request message length + * @param str_msg state transfer request message * @param gtid current state ID on this node * @param state current wsrep internal state buffer - * @param state_len current wsrep internal state buffer len * @param bypass bypass snapshot transfer, only transfer uuid:seqno pair */ typedef enum wsrep_cb_status (*wsrep_sst_donate_cb_t) ( void* app_ctx, void* recv_ctx, - const void* msg, - size_t msg_len, + const wsrep_buf_t* str_msg, const wsrep_gtid_t* state_id, - const char* state, - size_t state_len, + const wsrep_buf_t* state, wsrep_bool_t bypass ); @@ -448,8 +504,10 @@ typedef enum wsrep_cb_status (*wsrep_sst_donate_cb_t) ( * rest of the cluster. * * @param app_ctx application context + * + * @return wsrep_cb_status enum */ -typedef void (*wsrep_synced_cb_t) (void* app_ctx); +typedef enum wsrep_cb_status (*wsrep_synced_cb_t) (void* app_ctx); /*! @@ -469,21 +527,21 @@ struct wsrep_init_args /* Application initial state information. */ const wsrep_gtid_t* state_id; //!< Application state GTID - const char* state; //!< Initial state for wsrep provider - size_t state_len; //!< Length of state buffer + const wsrep_buf_t* state; //!< Initial state for wsrep provider /* Application callbacks */ - wsrep_log_cb_t logger_cb; //!< logging handler - wsrep_view_cb_t view_handler_cb; //!< group view change handler + wsrep_log_cb_t logger_cb; //!< logging handler + wsrep_connected_cb_t connected_cb; //!< connected to group + wsrep_view_cb_t view_cb; //!< group view change handler + wsrep_sst_request_cb_t sst_request_cb; //!< SST request creator /* Applier callbacks */ - wsrep_apply_cb_t apply_cb; //!< apply callback - wsrep_commit_cb_t commit_cb; //!< commit callback - wsrep_unordered_cb_t unordered_cb; //!< callback for unordered actions + wsrep_apply_cb_t apply_cb; //!< apply callback + wsrep_unordered_cb_t unordered_cb; //!< callback for unordered actions /* State Snapshot Transfer callbacks */ - wsrep_sst_donate_cb_t sst_donate_cb; //!< starting to donate - wsrep_synced_cb_t synced_cb; //!< synced with group + wsrep_sst_donate_cb_t sst_donate_cb; //!< donate SST + wsrep_synced_cb_t synced_cb; //!< synced with group }; @@ -502,20 +560,13 @@ struct wsrep_stats_var const char* name; //!< variable name wsrep_var_type_t type; //!< variable value type union { - int64_t _integer64; + int64_t _int64; double _double; const char* _string; } value; //!< variable value }; -/*! Abstract data buffer structure */ -typedef struct wsrep_buf -{ - const void* ptr; /*!< Pointer to data buffer */ - size_t len; /*!< Length of buffer */ -} wsrep_buf_t; - /*! Key struct used to pass certification keys for transaction handling calls. * A key consists of zero or more key parts. */ typedef struct wsrep_key @@ -526,7 +577,7 @@ typedef struct wsrep_key /*! Key type: * EXCLUSIVE conflicts with any key type - * SEMI reserved. If not supported, should be interpeted as EXCLUSIVE + * SEMI reserved. If not supported, should be interpreted as EXCLUSIVE * SHARED conflicts only with EXCLUSIVE keys */ typedef enum wsrep_key_type { @@ -549,13 +600,6 @@ typedef enum wsrep_data_type } wsrep_data_type_t; -/*! Transaction handle struct passed for wsrep transaction handling calls */ -typedef struct wsrep_ws_handle -{ - wsrep_trx_id_t trx_id; //!< transaction ID - void* opaque; //!< opaque provider transaction context data -} wsrep_ws_handle_t; - /*! * @brief Helper method to reset trx writeset handle state when trx id changes * @@ -585,11 +629,11 @@ typedef struct wsrep_po_handle { void* opaque; } wsrep_po_handle_t; static const wsrep_po_handle_t WSREP_PO_INITIALIZER = { NULL }; -typedef struct wsrep wsrep_t; +typedef struct wsrep_st wsrep_t; /*! * wsrep interface for dynamically loadable libraries */ -struct wsrep { +struct wsrep_st { const char *version; //!< interface version string @@ -603,11 +647,15 @@ struct wsrep { const struct wsrep_init_args* args); /*! - * @brief Returns provider capabilities flag bitmap + * @brief Returns provider capabilities bitmap + * + * Note that these are potential provider capabilities. Provider will + * offer only capabilities supported by all members in the view + * (see wsrep_view_info). * * @param wsrep provider handle */ - uint64_t (*capabilities) (wsrep_t* wsrep); + wsrep_cap_t (*capabilities) (wsrep_t* wsrep); /*! * @brief Passes provider-specific configuration string to provider. @@ -616,7 +664,7 @@ struct wsrep { * @param conf configuration string * * @retval WSREP_OK configuration string was parsed successfully - * @retval WSREP_WARNING could't not parse conf string, no action taken + * @retval WSREP_WARNING could not parse configuration string, no action taken */ wsrep_status_t (*options_set) (wsrep_t* wsrep, const char* conf); @@ -633,7 +681,7 @@ struct wsrep { /*! * @brief Opens connection to cluster * - * Returns when either node is ready to operate as a part of the clsuter + * Returns when either node is ready to operate as a part of the cluster * or fails to reach operating status. * * @param wsrep provider handle @@ -642,7 +690,7 @@ struct wsrep { * @param state_donor name of the node to be asked for state transfer. * @param bootstrap a flag to request initialization of a new wsrep * service rather then a connection to the existing one. - * clister_url may still carry important initialization + * cluster_url may still carry important initialization * parameters, like backend spec and/or listen address. */ wsrep_status_t (*connect) (wsrep_t* wsrep, @@ -672,52 +720,100 @@ struct wsrep { wsrep_status_t (*recv)(wsrep_t* wsrep, void* recv_ctx); /*! - * @brief Replicates/logs result of transaction to other nodes and allocates - * required resources. + * @brief Tells provider that a given writeset has a read view associated + * with it. + * + * @param wsrep provider handle + * @param handle writeset handle + * @param rv read view GTID established by the caller or if NULL, + * provider will infer it internally. + */ + wsrep_status_t (*assign_read_view)(wsrep_t* wsrep, + wsrep_ws_handle_t* handle, + const wsrep_gtid_t* rv); + + /*! + * @brief Certifies transaction with provider. * * Must be called before transaction commit. Returns success code, which * caller must check. - * In case of WSREP_OK, starts commit critical section, transaction can - * commit. Otherwise transaction must rollback. + * + * In case of WSREP_OK, transaction can proceed to commit. + * Otherwise transaction must rollback. + * + * In case of a failure there are two conceptually different situations: + * - the writeset was not ordered. In that case meta struct shall contain + * undefined GTID: WSREP_UUID_UNDEFINED:WSREP_SEQNO_UNDEFINED. + * - the writeset was successfully ordered, but failed certification. + * In this case meta struct shall contain a valid GTID. + * + * Regardless of the return code, if meta struct contains a valid GTID + * the commit order critical section must be entered with that GTID. * * @param wsrep provider handle - * @param ws_handle writeset of committing transaction * @param conn_id connection ID + * @param ws_handle writeset of committing transaction * @param flags fine tuning the replication WSREP_FLAG_* * @param meta transaction meta data * - * @retval WSREP_OK cluster-wide commit succeeded + * @retval WSREP_OK writeset successfully certified, can commit * @retval WSREP_TRX_FAIL must rollback transaction * @retval WSREP_CONN_FAIL must close client connection * @retval WSREP_NODE_FAIL must close all connections and reinit */ - wsrep_status_t (*pre_commit)(wsrep_t* wsrep, - wsrep_conn_id_t conn_id, - wsrep_ws_handle_t* ws_handle, - uint32_t flags, - wsrep_trx_meta_t* meta); + wsrep_status_t (*certify)(wsrep_t* wsrep, + wsrep_conn_id_t conn_id, + wsrep_ws_handle_t* ws_handle, + uint32_t flags, + wsrep_trx_meta_t* meta); /*! - * @brief Releases resources after transaction commit. + * @brief Enters commit order critical section. * - * Ends commit critical section. + * Anything executed between this call and commit_order_leave() will be + * executed in provider enforced order. * * @param wsrep provider handle - * @param ws_handle writeset of committing transaction - * @retval WSREP_OK post_commit succeeded + * @param ws_handle internal provider writeset handle + * @param meta transaction meta data + * + * @retval WSREP_OK commit order entered successfully + * @retval WSREP_NODE_FAIL must close all connections and reinit + */ + wsrep_status_t (*commit_order_enter)(wsrep_t* wsrep, + const wsrep_ws_handle_t* ws_handle, + const wsrep_trx_meta_t* meta); + + /*! + * @brief Leaves commit order critical section + * + * Anything executed between commit_order_enter() and this call will be + * executed in provider enforced order. + * + * @param wsrep provider handle + * @param ws_handle internal provider writeset handle + * @param meta transaction meta data + * @param error buffer containing error info (null/empty for no error) + * + * @retval WSREP_OK commit order left successfully + * @retval WSREP_NODE_FAIL must close all connections and reinit */ - wsrep_status_t (*post_commit) (wsrep_t* wsrep, - wsrep_ws_handle_t* ws_handle); + wsrep_status_t (*commit_order_leave)(wsrep_t* wsrep, + const wsrep_ws_handle_t* ws_handle, + const wsrep_trx_meta_t* meta, + const wsrep_buf_t* error); /*! - * @brief Releases resources after transaction rollback. + * @brief Releases resources after transaction commit/rollback. + * + * Ends total order critical section. * * @param wsrep provider handle * @param ws_handle writeset of committing transaction - * @retval WSREP_OK post_rollback succeeded + * @retval WSREP_OK release succeeded */ - wsrep_status_t (*post_rollback)(wsrep_t* wsrep, - wsrep_ws_handle_t* ws_handle); + wsrep_status_t (*release) (wsrep_t* wsrep, + wsrep_ws_handle_t* ws_handle); /*! * @brief Replay trx as a slave writeset @@ -743,24 +839,44 @@ struct wsrep { void* trx_ctx); /*! - * @brief Abort pre_commit() call of another thread. + * @brief Abort certify() call of another thread. * * It is possible, that some high-priority transaction needs to abort - * another transaction which is in pre_commit() call waiting for resources. + * another transaction which is in certify() call waiting for resources. * - * The kill routine checks that abort is not attmpted against a transaction + * The kill routine checks that abort is not attempted against a transaction * which is front of the caller (in total order). * + * If the abort was successful, the victim sequence number is stored + * into location pointed by the victim_seqno. + * * @param wsrep provider handle * @param bf_seqno seqno of brute force trx, running this cancel * @param victim_trx transaction to be aborted, and which is committing + * @param victim_seqno seqno of the victim transaction if assigned * - * @retval WSREP_OK abort secceded - * @retval WSREP_WARNING abort failed + * @retval WSREP_OK abort succeeded + * @retval WSREP_NOT_ALLOWED the provider declined the abort request + * @retval WSREP_TRX_MISSING the victim_trx was missing + * @retval WSREP_WARNING abort failed */ - wsrep_status_t (*abort_pre_commit)(wsrep_t* wsrep, - wsrep_seqno_t bf_seqno, - wsrep_trx_id_t victim_trx); + wsrep_status_t (*abort_certification)(wsrep_t* wsrep, + wsrep_seqno_t bf_seqno, + wsrep_trx_id_t victim_trx, + wsrep_seqno_t* victim_seqno); + + /*! + * @brief Send a rollback fragment on behalf of trx + * + * @param wsrep provider handle + * @param trx transaction to be rolled back + * @param data data to append to the fragment + * + * @retval WSREP_OK rollback fragment sent successfully + */ + wsrep_status_t (*rollback)(wsrep_t* wsrep, + wsrep_trx_id_t trx, + const wsrep_buf_t* data); /*! * @brief Appends a row reference to transaction writeset @@ -772,7 +888,7 @@ struct wsrep { * @param ws_handle writeset handle * @param keys array of keys * @param count length of the array of keys - * @param type type ot the key + * @param type type of the key * @param copy can be set to FALSE if keys persist through commit. */ wsrep_status_t (*append_key)(wsrep_t* wsrep, @@ -797,33 +913,54 @@ struct wsrep { * @param type type of data * @param copy can be set to FALSE if data persists through commit. */ - wsrep_status_t (*append_data)(wsrep_t* wsrep, - wsrep_ws_handle_t* ws_handle, - const struct wsrep_buf* data, - size_t count, - enum wsrep_data_type type, - wsrep_bool_t copy); + wsrep_status_t (*append_data)(wsrep_t* wsrep, + wsrep_ws_handle_t* ws_handle, + const wsrep_buf_t* data, + size_t count, + enum wsrep_data_type type, + wsrep_bool_t copy); /*! - * @brief Get causal ordering for read operation + * @brief Blocks until the given GTID is committed * - * This call will block until causal ordering with all possible - * preceding writes in the cluster is guaranteed. If pointer to - * gtid is non-null, the call stores the global transaction ID - * of the last transaction which is guaranteed to be ordered - * causally before this call. + * This call will block the caller until the given GTID + * is guaranteed to be committed, or until a timeout occurs. + * The timeout value is given in parameter tout, if tout is -1, + * then the global causal read timeout applies. * - * @param wsrep provider handle - * @param gtid location to store GTID + * If no pointer upto is provided the call will block until + * causal ordering with all possible preceding writes in the + * cluster is guaranteed. + * + * If pointer to gtid is non-null, the call stores the global + * transaction ID of the last transaction which is guaranteed + * to be committed when the call returns. + * + * @param wsrep provider handle + * @param upto gtid to wait upto + * @param tout timeout in seconds + * -1 wait for global causal read timeout + * @param gtid location to store GTID + */ + wsrep_status_t (*sync_wait)(wsrep_t* wsrep, + wsrep_gtid_t* upto, + int tout, + wsrep_gtid_t* gtid); + + /*! + * @brief Returns the last committed gtid + * + * @param gtid location to store GTID */ - wsrep_status_t (*causal_read)(wsrep_t* wsrep, wsrep_gtid_t* gtid); + wsrep_status_t (*last_committed_id)(wsrep_t* wsrep, + wsrep_gtid_t* gtid); /*! * @brief Clears allocated connection context. * * Whenever a new connection ID is passed to wsrep provider through * any of the API calls, a connection context is allocated for this - * connection. This call is to explicitly notify provider fo connection + * connection. This call is to explicitly notify provider of connection * closing. * * @param wsrep provider handle @@ -837,28 +974,51 @@ struct wsrep { /*! * @brief Replicates a query and starts "total order isolation" section. * + * Regular mode: + * * Replicates the action spec and returns success code, which caller must * check. Total order isolation continues until to_execute_end() is called. + * Regular "total order isolation" is achieved by calling to_execute_start() + * with WSREP_FLAG_TRX_START and WSREP_FLAG_TRX_END set. + * + * Two-phase mode: + * + * In this mode a query execution is split in two phases. The first phase is + * acquiring total order isolation to access critical section and the + * second phase is to release acquired resources in total order. + * + * To start the first phase the call is made with WSREP_FLAG_TRX_START set. + * The action is replicated and success code is returned. The total order + * isolation continues until to_execute_end() is called. However, the provider + * will keep the reference to the operation for conflict resolution purposes. + * + * The second phase is started with WSREP_FLAG_TRX_END set. Provider + * returns once it has achieved total ordering isolation for second phase. + * Total order isolation continues until to_execute_end() is called. + * All references to the operation are cleared by provider before + * call to to_execute_end() returns. * * @param wsrep provider handle * @param conn_id connection ID * @param keys array of keys - * @param keys_num lenght of the array of keys + * @param keys_num length of the array of keys * @param action action buffer array to be executed * @param count action buffer count + * @param flags flags * @param meta transaction meta data * * @retval WSREP_OK cluster commit succeeded * @retval WSREP_CONN_FAIL must close client connection * @retval WSREP_NODE_FAIL must close all connections and reinit */ - wsrep_status_t (*to_execute_start)(wsrep_t* wsrep, - wsrep_conn_id_t conn_id, - const wsrep_key_t* keys, - size_t keys_num, - const struct wsrep_buf* action, - size_t count, - wsrep_trx_meta_t* meta); + wsrep_status_t (*to_execute_start)(wsrep_t* wsrep, + wsrep_conn_id_t conn_id, + const wsrep_key_t* keys, + size_t keys_num, + const wsrep_buf_t* action, + size_t count, + uint32_t flags, + wsrep_trx_meta_t* meta); /*! * @brief Ends the total order isolation section. @@ -866,14 +1026,18 @@ struct wsrep { * Marks the end of total order isolation. TO locks are freed * and other transactions are free to commit from this point on. * - * @param wsrep provider handle + * @param wsrep provider handle * @param conn_id connection ID + * @param error error information about TOI operation (empty for no error) * * @retval WSREP_OK cluster commit succeeded * @retval WSREP_CONN_FAIL must close client connection * @retval WSREP_NODE_FAIL must close all connections and reinit */ - wsrep_status_t (*to_execute_end)(wsrep_t* wsrep, wsrep_conn_id_t conn_id); + wsrep_status_t (*to_execute_end)(wsrep_t* wsrep, + wsrep_conn_id_t conn_id, + const wsrep_buf_t* error); + /*! * @brief Collects preordered replication events into a writeset. @@ -888,11 +1052,11 @@ struct wsrep { * @retval WSREP_TRX_FAIL operation failed (e.g. trx size exceeded limit) * @retval WSREP_NODE_FAIL must close all connections and reinit */ - wsrep_status_t (*preordered_collect) (wsrep_t* wsrep, - wsrep_po_handle_t* handle, - const struct wsrep_buf* data, - size_t count, - wsrep_bool_t copy); + wsrep_status_t (*preordered_collect) (wsrep_t* wsrep, + wsrep_po_handle_t* handle, + const wsrep_buf_t* data, + size_t count, + wsrep_bool_t copy); /*! * @brief "Commits" preordered writeset to cluster. @@ -943,20 +1107,18 @@ struct wsrep { * @param wsrep provider handle * @param state_id state ID * @param state initial state provided by SST donor - * @param state_len length of state buffer * @param rcode 0 or negative error code of the operation. */ wsrep_status_t (*sst_received)(wsrep_t* wsrep, const wsrep_gtid_t* state_id, - const void* state, - size_t state_len, + const wsrep_buf_t* state, int rcode); /*! * @brief Generate request for consistent snapshot. * - * If successfull, this call will generate internally SST request + * If successful, this call will generate internally SST request * which in turn triggers calling SST donate callback on the nodes * specified in donor_spec. If donor_spec is null, callback is * called only locally. This call will block until sst_sent is called @@ -967,13 +1129,12 @@ struct wsrep { * @param msg_len length of context message * @param donor_spec list of snapshot donors */ - wsrep_status_t (*snapshot)(wsrep_t* wsrep, - const void* msg, - size_t msg_len, - const char* donor_spec); + wsrep_status_t (*snapshot)(wsrep_t* wsrep, + const wsrep_buf_t* msg, + const char* donor_spec); /*! - * @brief Returns an array fo status variables. + * @brief Returns an array of status variables. * Array is terminated by Null variable name. * * @param wsrep provider handle @@ -1020,7 +1181,7 @@ struct wsrep { * @brief Request to resynchronize with cluster. * * Effectively turns on flow control. Asynchronous - actual synchronization - * event to be deliverred via sync_cb. + * event to be delivered via sync_cb. */ wsrep_status_t (*resync) (wsrep_t* wsrep); @@ -1086,7 +1247,7 @@ struct wsrep { void (*free)(wsrep_t* wsrep); void *dlh; //!< reserved for future use - void *ctx; //!< reserved for implemetation private context + void *ctx; //!< reserved for implementation private context }; @@ -1094,7 +1255,7 @@ struct wsrep { * * @brief Loads wsrep library * - * @param spec path to wsrep library. If NULL or WSREP_NONE initialises dummy + * @param spec path to wsrep library. If NULL or WSREP_NONE initializes dummy * pass-through implementation. * @param hptr wsrep handle * @param log_cb callback to handle loader messages. Otherwise writes to stderr. diff --git a/wsrep/wsrep_dummy.c b/wsrep/wsrep_dummy.c index e48dcff39a1..9000261af3d 100644 --- a/wsrep/wsrep_dummy.c +++ b/wsrep/wsrep_dummy.c @@ -19,6 +19,7 @@ #include "wsrep_api.h" #include <errno.h> +#include <stdbool.h> #include <string.h> /*! Dummy backend context. */ @@ -62,7 +63,7 @@ static wsrep_status_t dummy_init (wsrep_t* w, return WSREP_OK; } -static uint64_t dummy_capabilities (wsrep_t* w __attribute__((unused))) +static wsrep_cap_t dummy_capabilities (wsrep_t* w __attribute__((unused))) { return 0; } @@ -84,15 +85,8 @@ static wsrep_status_t dummy_options_set( static char* dummy_options_get (wsrep_t* w) { - char *options; - - WSREP_DBUG_ENTER(w); - options= WSREP_DUMMY(w)->options; - - if (options) - options= strdup(WSREP_DUMMY(w)->options); - - return options; + WSREP_DBUG_ENTER(w); + return strdup(WSREP_DUMMY(w)->options); } static wsrep_status_t dummy_connect( @@ -119,7 +113,16 @@ static wsrep_status_t dummy_recv(wsrep_t* w, return WSREP_OK; } -static wsrep_status_t dummy_pre_commit( +static wsrep_status_t dummy_assign_read_view( + wsrep_t* w, + wsrep_ws_handle_t* ws_handle __attribute__((unused)), + const wsrep_gtid_t* rv __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_certify( wsrep_t* w, const wsrep_conn_id_t conn_id __attribute__((unused)), wsrep_ws_handle_t* ws_handle __attribute__((unused)), @@ -130,15 +133,26 @@ static wsrep_status_t dummy_pre_commit( return WSREP_OK; } -static wsrep_status_t dummy_post_commit( +static wsrep_status_t dummy_commit_order_enter( wsrep_t* w, - wsrep_ws_handle_t* ws_handle __attribute__((unused))) + const wsrep_ws_handle_t* ws_handle __attribute__((unused)), + const wsrep_trx_meta_t* meta __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; } -static wsrep_status_t dummy_post_rollback( +static wsrep_status_t dummy_commit_order_leave( + wsrep_t* w, + const wsrep_ws_handle_t* ws_handle __attribute__((unused)), + const wsrep_trx_meta_t* meta __attribute__((unused)), + const wsrep_buf_t* error __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_release( wsrep_t* w, wsrep_ws_handle_t* ws_handle __attribute__((unused))) { @@ -155,10 +169,20 @@ static wsrep_status_t dummy_replay_trx( return WSREP_OK; } -static wsrep_status_t dummy_abort_pre_commit( +static wsrep_status_t dummy_abort_certification( wsrep_t* w, const wsrep_seqno_t bf_seqno __attribute__((unused)), - const wsrep_trx_id_t trx_id __attribute__((unused))) + const wsrep_trx_id_t trx_id __attribute__((unused)), + wsrep_seqno_t *victim_seqno __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_rollback( + wsrep_t* w, + const wsrep_trx_id_t trx __attribute__((unused)), + const wsrep_buf_t* data __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -170,7 +194,7 @@ static wsrep_status_t dummy_append_key( const wsrep_key_t* key __attribute__((unused)), const size_t key_num __attribute__((unused)), const wsrep_key_type_t key_type __attribute__((unused)), - const wsrep_bool_t copy __attribute__((unused))) + const bool copy __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -182,13 +206,23 @@ static wsrep_status_t dummy_append_data( const struct wsrep_buf* data __attribute__((unused)), const size_t count __attribute__((unused)), const wsrep_data_type_t type __attribute__((unused)), - const wsrep_bool_t copy __attribute__((unused))) + const bool copy __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_sync_wait( + wsrep_t* w, + wsrep_gtid_t* upto __attribute__((unused)), + int tout __attribute__((unused)), + wsrep_gtid_t* gtid __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; } -static wsrep_status_t dummy_causal_read( +static wsrep_status_t dummy_last_committed_id( wsrep_t* w, wsrep_gtid_t* gtid __attribute__((unused))) { @@ -211,6 +245,7 @@ static wsrep_status_t dummy_to_execute_start( const size_t key_num __attribute__((unused)), const struct wsrep_buf* data __attribute__((unused)), const size_t count __attribute__((unused)), + const uint32_t flags __attribute__((unused)), wsrep_trx_meta_t* meta __attribute__((unused))) { WSREP_DBUG_ENTER(w); @@ -219,7 +254,8 @@ static wsrep_status_t dummy_to_execute_start( static wsrep_status_t dummy_to_execute_end( wsrep_t* w, - const wsrep_conn_id_t conn_id __attribute__((unused))) + const wsrep_conn_id_t conn_id __attribute__((unused)), + const wsrep_buf_t* err __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -260,8 +296,7 @@ static wsrep_status_t dummy_sst_sent( static wsrep_status_t dummy_sst_received( wsrep_t* w, const wsrep_gtid_t* state_id __attribute__((unused)), - const void* state __attribute__((unused)), - const size_t state_len __attribute__((unused)), + const wsrep_buf_t* state __attribute__((unused)), const int rcode __attribute__((unused))) { WSREP_DBUG_ENTER(w); @@ -270,9 +305,8 @@ static wsrep_status_t dummy_sst_received( static wsrep_status_t dummy_snapshot( wsrep_t* w, - const void* msg __attribute__((unused)), - const size_t msg_len __attribute__((unused)), - const char* donor_spec __attribute__((unused))) + const wsrep_buf_t* msg __attribute__((unused)), + const char* donor_spec __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -325,10 +359,10 @@ static wsrep_status_t dummy_resync (wsrep_t* w) } static wsrep_status_t dummy_lock (wsrep_t* w, - const char* s __attribute__((unused)), - wsrep_bool_t r __attribute__((unused)), - uint64_t o __attribute__((unused)), - int64_t t __attribute__((unused))) + const char* s __attribute__((unused)), + bool r __attribute__((unused)), + uint64_t o __attribute__((unused)), + int64_t t __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_NOT_IMPLEMENTED; @@ -342,13 +376,13 @@ static wsrep_status_t dummy_unlock (wsrep_t* w, return WSREP_OK; } -static wsrep_bool_t dummy_is_locked (wsrep_t* w, - const char* s __attribute__((unused)), - uint64_t* o __attribute__((unused)), - wsrep_uuid_t* t __attribute__((unused))) +static bool dummy_is_locked (wsrep_t* w, + const char* s __attribute__((unused)), + uint64_t* o __attribute__((unused)), + wsrep_uuid_t* t __attribute__((unused))) { WSREP_DBUG_ENTER(w); - return 0; + return false; } static wsrep_t dummy_iface = { @@ -360,14 +394,18 @@ static wsrep_t dummy_iface = { &dummy_connect, &dummy_disconnect, &dummy_recv, - &dummy_pre_commit, - &dummy_post_commit, - &dummy_post_rollback, + &dummy_assign_read_view, + &dummy_certify, + &dummy_commit_order_enter, + &dummy_commit_order_leave, + &dummy_release, &dummy_replay_trx, - &dummy_abort_pre_commit, + &dummy_abort_certification, + &dummy_rollback, &dummy_append_key, &dummy_append_data, - &dummy_causal_read, + &dummy_sync_wait, + &dummy_last_committed_id, &dummy_free_connection, &dummy_to_execute_start, &dummy_to_execute_end, diff --git a/wsrep/wsrep_gtid.c b/wsrep/wsrep_gtid.c index 45148785c25..a02543ab523 100644 --- a/wsrep/wsrep_gtid.c +++ b/wsrep/wsrep_gtid.c @@ -53,7 +53,7 @@ wsrep_gtid_scan(const char* str, size_t str_len, wsrep_gtid_t* gtid) /*! * Write GTID to string - * @return length of GTID stirng representation of -EMSGSIZE if string is too + * @return length of GTID string representation or -EMSGSIZE if string is too * short */ int diff --git a/wsrep/wsrep_listener.c b/wsrep/wsrep_listener.c new file mode 100644 index 00000000000..7d1558c3014 --- /dev/null +++ b/wsrep/wsrep_listener.c @@ -0,0 +1,261 @@ +/* Copyright (C) 2012 Codership Oy <info@codersihp.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/*! @file Example of wsrep event listener. Outputs description of received + * events to stdout. To get a general picture you should start with + * main() function. */ + +#include <wsrep_api.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <signal.h> +#include <pthread.h> + +/*! This is global application context, it will be used by wsrep callbacks */ +struct application_context +{}; + +static struct application_context global_ctx; + +/*! This is receiving thread context, it will be used by wsrep callbacks */ +struct receiver_context +{ + char msg[4096]; +}; + +/* wsrep provider handle (global for simplicty) */ +static wsrep_t* wsrep = NULL; + +/*! This is a logger callback which library will be using to log events. */ +static void +logger_cb (wsrep_log_level_t level __attribute__((unused)), const char* msg) +{ + fprintf (stderr, "WSREP: %s\n", msg); +} + +/*! This will be called on cluster view change (nodes joining, leaving, etc.). + * Each view change is the point where application may be pronounced out of + * sync with the current cluster view and need state transfer. + * It is guaranteed that no other callbacks are called concurrently with it. */ +static wsrep_cb_status_t +view_cb (void* app_ctx __attribute__((unused)), + void* recv_ctx __attribute__((unused)), + const wsrep_view_info_t* view, + const char* state __attribute__((unused)), + size_t state_len __attribute__((unused))) +{ + printf ("New cluster membership view: %d nodes, my index is %d, " + "global seqno: %lld\n", + view->memb_num, view->my_idx, (long long)view->state_id.seqno); + + return WSREP_CB_SUCCESS; +} + +/*! This will be called on cluster view change (nodes joining, leaving, etc.). + * Each view change is the point where application may be pronounced out of + * sync with the current cluster view and need state transfer. + * It is guaranteed that no other callbacks are called concurrently with it. */ +static wsrep_cb_status_t +sst_request_cb (void** sst_req, + size_t* sst_req_len) +{ + /* For simplicity we're skipping state transfer by using magic string + * as a state transfer request. + * This node will not be considered JOINED (having full state) + * by other cluster members. */ + *sst_req = strdup(WSREP_STATE_TRANSFER_NONE); + + if (*sst_req) + *sst_req_len = strlen(*sst_req) + 1; + else + *sst_req_len = -ENOMEM; + + return WSREP_CB_SUCCESS; +} + +/*! This is called to "apply" writeset. + * If writesets don't conflict on keys, it may be called concurrently to + * utilize several CPU cores. */ +static wsrep_cb_status_t +apply_cb (void* recv_ctx, + const wsrep_ws_handle_t* ws_handle __attribute__((unused)), + uint32_t flags __attribute__((unused)), + const wsrep_buf_t* ws __attribute__((unused)), + const wsrep_trx_meta_t* meta, + wsrep_bool_t* exit_loop __attribute__((unused))) +{ + struct receiver_context* ctx = (struct receiver_context*)recv_ctx; + + snprintf (ctx->msg, sizeof(ctx->msg), + "Got writeset %lld, size %zu", (long long)meta->gtid.seqno, + ws->len); + + bool const commit = flags & (WSREP_FLAG_TRX_END | WSREP_FLAG_ROLLBACK); + + wsrep->commit_order_enter(wsrep, ws_handle); + if (commit) puts(ctx->msg); + wsrep->commit_order_leave(wsrep, ws_handle, NULL); + + return WSREP_CB_SUCCESS; +} + +/* The following callbacks are stubs and not used in this example. */ +static wsrep_cb_status_t +unordered_cb(void* recv_ctx __attribute__((unused)), + const wsrep_buf_t* data __attribute__((unused))) +{ + return WSREP_CB_SUCCESS; +} + +static wsrep_cb_status_t +sst_donate_cb (void* app_ctx __attribute__((unused)), + void* recv_ctx __attribute__((unused)), + const wsrep_buf_t* msg __attribute__((unused)), + const wsrep_gtid_t* state_id __attribute__((unused)), + const wsrep_buf_t* state __attribute__((unused)), + wsrep_bool_t bypass __attribute__((unused))) +{ + return WSREP_CB_SUCCESS; +} + +static wsrep_cb_status_t synced_cb (void* app_ctx __attribute__((unused))) +{ + return WSREP_CB_SUCCESS; +} + +/* This is the listening thread. It blocks in wsrep::recv() call until + * disconnect from cluster. It will apply and commit writesets through the + * callbacks defined avbove. */ +static void* +recv_thread (void* arg) +{ + struct receiver_context* ctx = (struct receiver_context*)arg; + + wsrep_status_t rc = wsrep->recv(wsrep, ctx); + + fprintf (stderr, "Receiver exited with code %d", rc); + + return NULL; +} + +/* This is a signal handler to demonstrate graceful cluster leave. */ +static void +graceful_leave (int signum) +{ + printf ("Got signal %d, exiting...\n", signum); + wsrep->disconnect(wsrep); +} + +int main (int argc, char* argv[]) +{ + if (argc != 4) + { + fprintf (stderr, "Usage: %s </path/to/wsrep/provider> <wsrep URI> " + "<cluster name>\n", argv[0]); + exit (EXIT_FAILURE); + } + + const char* const wsrep_provider = argv[1]; + const char* const wsrep_uri = argv[2]; + const char* const cluster_name = argv[3]; + + /* Now let's load and initialize provider */ + wsrep_status_t rc = wsrep_load (wsrep_provider, &wsrep, logger_cb); + if (WSREP_OK != rc) + { + fprintf (stderr, "Failed to load wsrep provider '%s'\n",wsrep_provider); + exit (EXIT_FAILURE); + } + + wsrep_gtid_t state_id = { WSREP_UUID_UNDEFINED, WSREP_SEQNO_UNDEFINED }; + + /* wsrep provider initialization arguments */ + struct wsrep_init_args wsrep_args = + { + .app_ctx = &global_ctx, + + .node_name = "example listener", + .node_address = "", + .node_incoming = "", + .data_dir = ".", // working directory + .options = "", + .proto_ver = 127, // maximum supported application event protocol + + .state_id = &state_id, + .state = NULL, + + .logger_cb = logger_cb, + .view_cb = view_cb, + .sst_request_cb = sst_request_cb, + .apply_cb = apply_cb, + .unordered_cb = unordered_cb, + .sst_donate_cb = sst_donate_cb, + .synced_cb = synced_cb + }; + + rc = wsrep->init(wsrep, &wsrep_args); + if (WSREP_OK != rc) + { + fprintf (stderr, "wsrep::init() failed: %d\n", rc); + exit (EXIT_FAILURE); + } + + /* Connect to cluster */ + rc = wsrep->connect (wsrep, cluster_name, wsrep_uri, "", 0); + if (0 != rc) + { + fprintf (stderr, + "wsrep::connect() failed: %d (%s)\n", rc, strerror(-rc)); + exit (EXIT_FAILURE); + } + + /* Now let's start several listening threads*/ + int const num_threads = 4; + struct receiver_context thread_ctx[num_threads]; + pthread_t threads[num_threads]; + + int i; + for (i = 0; i < num_threads; i++) + { + int err = pthread_create ( + &threads[i], NULL, recv_thread, &thread_ctx[i]); + + if (err) + { + fprintf (stderr, "Failed to start thread %d: %d (%s)", + i, err, strerror(err)); + exit (EXIT_FAILURE); + } + } + + signal (SIGTERM, graceful_leave); + signal (SIGINT, graceful_leave); + + /* Listening threads are now running and receiving writesets. Wait for them + * to join. Threads will join after signal handler closes wsrep connection*/ + for (i = 0; i < num_threads; i++) + { + pthread_join (threads[i], NULL); + } + + /* Unload provider after nobody uses it any more. */ + wsrep_unload (wsrep); + + return 0; +} diff --git a/wsrep/wsrep_loader.c b/wsrep/wsrep_loader.c index 1321538742f..31618de420e 100644 --- a/wsrep/wsrep_loader.c +++ b/wsrep/wsrep_loader.c @@ -56,9 +56,10 @@ static int wsrep_check_iface_version(const char* found, const char* iface_ver) static int verify(const wsrep_t *wh, const char *iface_ver) { char msg[128]; + const size_t msg_len = sizeof(msg); #define VERIFY(_p) if (!(_p)) { \ - snprintf(msg, sizeof(msg), "wsrep_load(): verify(): %s\n", # _p); \ + snprintf(msg, msg_len, "wsrep_load(): verify(): %s\n", # _p); \ logger (WSREP_LOG_ERROR, msg); \ return EINVAL; \ } @@ -75,11 +76,13 @@ static int verify(const wsrep_t *wh, const char *iface_ver) VERIFY(wh->connect); VERIFY(wh->disconnect); VERIFY(wh->recv); - VERIFY(wh->pre_commit); - VERIFY(wh->post_commit); - VERIFY(wh->post_rollback); + VERIFY(wh->assign_read_view); + VERIFY(wh->certify); + VERIFY(wh->commit_order_enter); + VERIFY(wh->commit_order_leave); + VERIFY(wh->release); VERIFY(wh->replay_trx); - VERIFY(wh->abort_pre_commit); + VERIFY(wh->abort_certification); VERIFY(wh->append_key); VERIFY(wh->append_data); VERIFY(wh->free_connection); @@ -134,8 +137,9 @@ int wsrep_load(const char *spec, wsrep_t **hptr, wsrep_log_cb_t log_cb) int ret = 0; void *dlh = NULL; wsrep_loader_fun dlfun; - char msg[1025]; - msg[sizeof(msg)-1] = 0; + char msg[1024]; + const size_t msg_len = sizeof(msg) - 1; + msg[msg_len] = 0; if (NULL != log_cb) logger = log_cb; @@ -143,7 +147,7 @@ int wsrep_load(const char *spec, wsrep_t **hptr, wsrep_log_cb_t log_cb) if (!(spec && hptr)) return EINVAL; - snprintf (msg, sizeof(msg)-1, + snprintf (msg, msg_len, "wsrep_load(): loading provider library '%s'", spec); logger (WSREP_LOG_INFO, msg); @@ -161,7 +165,7 @@ int wsrep_load(const char *spec, wsrep_t **hptr, wsrep_log_cb_t log_cb) } if (!(dlh = dlopen(spec, RTLD_NOW | RTLD_LOCAL))) { - snprintf(msg, sizeof(msg)-1, "wsrep_load(): dlopen(): %s", dlerror()); + snprintf(msg, msg_len, "wsrep_load(): dlopen(): %s", dlerror()); logger (WSREP_LOG_ERROR, msg); ret = EINVAL; goto out; @@ -178,14 +182,14 @@ int wsrep_load(const char *spec, wsrep_t **hptr, wsrep_log_cb_t log_cb) } if ((ret = (*dlfun)(*hptr)) != 0) { - snprintf(msg, sizeof(msg)-1, "wsrep_load(): loader failed: %s", + snprintf(msg, msg_len, "wsrep_load(): loader failed: %s", strerror(ret)); logger (WSREP_LOG_ERROR, msg); goto out; } if ((ret = verify(*hptr, WSREP_INTERFACE_VERSION)) != 0) { - snprintf (msg, sizeof(msg)-1, + snprintf (msg, msg_len, "wsrep_load(): interface version mismatch: my version %s, " "provider version %s", WSREP_INTERFACE_VERSION, (*hptr)->version); @@ -201,7 +205,7 @@ out: free(*hptr); *hptr = NULL; } else { - snprintf (msg, sizeof(msg)-1, + snprintf (msg, msg_len, "wsrep_load(): %s %s by %s loaded successfully.", (*hptr)->provider_name, (*hptr)->provider_version, (*hptr)->provider_vendor); diff --git a/wsrep/wsrep_uuid.c b/wsrep/wsrep_uuid.c index 54ae4ab5ed5..419594db127 100644 --- a/wsrep/wsrep_uuid.c +++ b/wsrep/wsrep_uuid.c @@ -19,6 +19,7 @@ #include <errno.h> #include <ctype.h> #include <stdio.h> +#include <string.h> #include "wsrep_api.h" @@ -81,3 +82,13 @@ wsrep_uuid_print (const wsrep_uuid_t* uuid, char* str, size_t str_len) return -EMSGSIZE; } } + +/*! + * Compare two UUIDs + * @return -1, 0, 1 if lhs is respectively smaller, equal, or greater than rhs + */ +int +wsrep_uuid_compare (const wsrep_uuid_t* lhs, const wsrep_uuid_t* rhs) +{ + return memcmp(lhs, rhs, sizeof(wsrep_uuid_t)); +} |