diff options
author | Brave Galera Crew <devel@codership.com> | 2019-01-23 15:30:00 +0400 |
---|---|---|
committer | Sergey Vojtovich <svoj@mariadb.org> | 2019-01-23 15:30:00 +0400 |
commit | 36a2a185fe18d31a644da46cfabd9757a379280c (patch) | |
tree | 00ca186ce2cfdc3ab7e4979336a384e2b51c5aa9 | |
parent | 382115b99297ceaa4c3067f79efb5c2515013be5 (diff) | |
download | mariadb-git-36a2a185fe18d31a644da46cfabd9757a379280c.tar.gz |
Galera4
791 files changed, 27577 insertions, 8408 deletions
diff --git a/.gitmodules b/.gitmodules index 6419657e501..61d4c06dd4e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,7 @@ [submodule "storage/rocksdb/rocksdb"] path = storage/rocksdb/rocksdb url = https://github.com/facebook/rocksdb.git +[submodule "wsrep-lib"] + path = wsrep-lib + url = https://github.com/codership/wsrep-lib.git + branch = master diff --git a/CMakeLists.txt b/CMakeLists.txt index a139c9e5fa4..b7cf8d23308 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -143,6 +143,7 @@ INCLUDE(misc) INCLUDE(mysql_version) INCLUDE(cpack_source_ignore_files) INCLUDE(install_layout) +INCLUDE(submodules) INCLUDE(wsrep) INCLUDE(cpack_rpm) INCLUDE(cpack_deb) @@ -377,7 +378,6 @@ ENDIF() SET (MYSQLD_STATIC_PLUGIN_LIBS "" CACHE INTERNAL "") -INCLUDE(submodules) INCLUDE(mariadb_connector_c) # this does ADD_SUBDIRECTORY(libmariadb) # Add storage engines and plugins. @@ -405,7 +405,7 @@ IF(NOT WITHOUT_SERVER) ENDIF(WITH_EMBEDDED_SERVER) IF(WITH_WSREP) - ADD_SUBDIRECTORY(wsrep) + ADD_SUBDIRECTORY(wsrep-lib) ENDIF() ADD_SUBDIRECTORY(mysql-test) diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index 36d426257ea..19293e9a176 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -171,7 +171,7 @@ SETA(CPACK_RPM_server_PACKAGE_REQUIRES IF(WITH_WSREP) SETA(CPACK_RPM_server_PACKAGE_REQUIRES - "galera" "rsync" "lsof" "grep" "gawk" "iproute" + "galera-4" "rsync" "lsof" "grep" "gawk" "iproute" "coreutils" "findutils" "tar") ENDIF() diff --git a/cmake/make_dist.cmake.in b/cmake/make_dist.cmake.in index 6fad17137fd..8e77b700eb7 100644 --- a/cmake/make_dist.cmake.in +++ b/cmake/make_dist.cmake.in @@ -50,6 +50,14 @@ IF(GIT_EXECUTABLE) IF(NOT RESULT EQUAL 0) SET(GIT_EXECUTABLE) ENDIF() + EXECUTE_PROCESS( + COMMAND "${GIT_EXECUTABLE}" submodule foreach "${GIT_EXECUTABLE} checkout-index --all --prefix=${PACKAGE_DIR}/wsrep-lib/$path/" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/wsrep-lib + RESULT_VARIABLE RESULT + ) + IF(NOT RESULT EQUAL 0) + SET(GIT_EXECUTABLE) + ENDIF() ENDIF() CONFIGURE_FILE(${CMAKE_BINARY_DIR}/include/source_revision.h diff --git a/cmake/submodules.cmake b/cmake/submodules.cmake index 4181f4cd01e..c2a415c6063 100644 --- a/cmake/submodules.cmake +++ b/cmake/submodules.cmake @@ -14,16 +14,16 @@ IF(GIT_EXECUTABLE AND EXISTS "${CMAKE_SOURCE_DIR}/.git") SET(update_result 0) ELSEIF (cmake_update_submodules MATCHES force) MESSAGE(STATUS "Updating submodules (forced)") - EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init --force + EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init --force --recursive WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" RESULT_VARIABLE update_result) ELSEIF (cmake_update_submodules MATCHES yes) - EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init + EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init --recursive WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" RESULT_VARIABLE update_result) ELSE() MESSAGE(STATUS "Updating submodules") - EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init + EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init --recursive WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" RESULT_VARIABLE update_result) ENDIF() diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 9fa127380a4..44e00649993 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -24,12 +24,15 @@ ELSE() ENDIF() OPTION(WITH_WSREP "WSREP replication API (to use, e.g. Galera Replication library)" ${with_wsrep_default}) +OPTION(WITH_WSREP_ALL + "Build all components of WSREP (unit tests, sample programs)" + OFF) # 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 +FILE(STRINGS "${CMAKE_SOURCE_DIR}/wsrep-lib/wsrep-API/v26/wsrep_api.h" WSREP_API_VERSION LIMIT_COUNT 1 REGEX "WSREP_INTERFACE_VERSION") STRING(REGEX MATCH "([0-9]+)" WSREP_API_VERSION "${WSREP_API_VERSION}") @@ -40,4 +43,12 @@ SET(WSREP_PROC_INFO ${WITH_WSREP}) IF(WITH_WSREP) SET(WSREP_PATCH_VERSION "wsrep_${WSREP_VERSION}") + if (NOT WITH_WSREP_ALL) + SET(WSREP_LIB_WITH_UNIT_TESTS OFF CACHE BOOL + "Disable unit tests for wsrep-lib") + SET(WSREP_LIB_WITH_DBSIM OFF CACHE BOOL + "Disable building dbsim for wsrep-lib") + endif() + INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/wsrep-lib/include) + INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/wsrep-lib/wsrep-API/v26) ENDIF() diff --git a/debian/control b/debian/control index 1588ade9153..2d3f0eb4aef 100644 --- a/debian/control +++ b/debian/control @@ -430,7 +430,7 @@ Recommends: libhtml-template-perl Pre-Depends: adduser (>= 3.40), debconf, mariadb-common (>= ${source:Version}) -Depends: galera-3 (>=25.3), +Depends: galera-4 (>=26.4), gawk, iproute | iproute2, libdbi-perl, diff --git a/extra/mariabackup/CMakeLists.txt b/extra/mariabackup/CMakeLists.txt index 02f2d1a3690..623e7460ee4 100644 --- a/extra/mariabackup/CMakeLists.txt +++ b/extra/mariabackup/CMakeLists.txt @@ -40,9 +40,6 @@ IF(NOT HAVE_SYSTEM_REGEX) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/pcre) ENDIF() -IF(WITH_WSREP) - INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/wsrep) -ENDIF() ADD_DEFINITIONS(-UMYSQL_SERVER) ######################################################################## diff --git a/include/mysql/service_wsrep.h b/include/mysql/service_wsrep.h index cefba6303fe..5aa97cdb47e 100644 --- a/include/mysql/service_wsrep.h +++ b/include/mysql/service_wsrep.h @@ -1,5 +1,20 @@ #ifndef MYSQL_SERVICE_WSREP_INCLUDED +#define MYSQL_SERVICE_WSREP_INCLUDED + +enum Wsrep_service_key_type +{ + WSREP_SERVICE_KEY_SHARED, + WSREP_SERVICE_KEY_REFERENCE, + WSREP_SERVICE_KEY_UPDATE, + WSREP_SERVICE_KEY_EXCLUSIVE +}; + +#if (defined (MYSQL_DYNAMIC_PLUGIN) && defined(MYSQL_SERVICE_WSREP_DYNAMIC_INCLUDED)) || (!defined(MYSQL_DYNAMIC_PLUGIN) && defined(MYSQL_SERVICE_WSREP_STATIC_INCLUDED)) + +#else + /* Copyright (c) 2015 MariaDB Corporation Ab + 2018 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 @@ -21,153 +36,92 @@ Interface to WSREP functionality in the server. For engines that want to support galera. */ - +#include <my_pthread.h> #ifdef __cplusplus -extern "C" { #endif -enum wsrep_conflict_state { - NO_CONFLICT, - MUST_ABORT, - ABORTING, - ABORTED, - MUST_REPLAY, - REPLAYING, - RETRY_AUTOCOMMIT, - CERT_FAILURE, -}; - -enum wsrep_exec_mode { - /* Transaction processing before replication. */ - LOCAL_STATE, - /* Slave thread applying write sets from other nodes or replaying thread. */ - REPL_RECV, - /* Total-order-isolation mode. */ - TOTAL_ORDER, - /* - Transaction procession after it has been replicated in prepare stage and - has passed certification. - */ - LOCAL_COMMIT -}; - -enum wsrep_query_state { - QUERY_IDLE, - QUERY_EXEC, - QUERY_COMMITTING, - QUERY_EXITING, - QUERY_ROLLINGBACK, -}; - -enum wsrep_trx_status { - WSREP_TRX_OK, - WSREP_TRX_CERT_FAIL, /* certification failure, must abort */ - WSREP_TRX_SIZE_EXCEEDED, /* trx size exceeded */ - WSREP_TRX_ERROR, /* native mysql error */ -}; - struct xid_t; -struct wsrep; struct wsrep_ws_handle; struct wsrep_buf; +/* Must match to definition in sql/mysqld.h */ +typedef int64 query_id_t; + + extern struct wsrep_service_st { - struct wsrep * (*get_wsrep_func)(); - my_bool (*get_wsrep_certify_nonPK_func)(); - my_bool (*get_wsrep_debug_func)(); - my_bool (*get_wsrep_drupal_282555_workaround_func)(); my_bool (*get_wsrep_recovery_func)(); - 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); + bool (*wsrep_consistency_check_func)(MYSQL_THD thd); + 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); - 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); - 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_wsrep_func)(MYSQL_THD thd); - char * (*wsrep_thd_query_func)(THD *thd); - enum wsrep_query_state (*wsrep_thd_query_state_func)(THD *thd); - const char * (*wsrep_thd_query_state_str_func)(THD *thd); - 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); - 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)(); + my_bool (*wsrep_on_func)(const MYSQL_THD thd); + bool (*wsrep_prepare_key_for_innodb_func)(MYSQL_THD thd, const unsigned char*, size_t, const unsigned char*, size_t, struct wsrep_buf*, size_t*); + void (*wsrep_thd_LOCK_func)(const MYSQL_THD thd); + void (*wsrep_thd_UNLOCK_func)(const MYSQL_THD thd); + const char * (*wsrep_thd_query_func)(const MYSQL_THD thd); + int (*wsrep_thd_retry_counter_func)(const MYSQL_THD thd); + bool (*wsrep_thd_ignore_table_func)(MYSQL_THD thd); + long long (*wsrep_thd_trx_seqno_func)(const MYSQL_THD thd); + my_bool (*wsrep_thd_is_aborting_func)(const MYSQL_THD thd); void (*wsrep_set_data_home_dir_func)(const char *data_dir); + my_bool (*wsrep_thd_is_BF_func)(const MYSQL_THD thd, my_bool sync); + my_bool (*wsrep_thd_is_local_func)(const MYSQL_THD thd); + void (*wsrep_thd_self_abort_func)(MYSQL_THD thd); + int (*wsrep_thd_append_key_func)(MYSQL_THD thd, const struct wsrep_key* key, + int n_keys, enum Wsrep_service_key_type); + const char* (*wsrep_thd_client_state_str_func)(const MYSQL_THD thd); + const char* (*wsrep_thd_client_mode_str_func)(const MYSQL_THD thd); + const char* (*wsrep_thd_transaction_state_str_func)(const MYSQL_THD thd); + query_id_t (*wsrep_thd_transaction_id_func)(const MYSQL_THD thd); + my_bool (*wsrep_thd_bf_abort_func)(const MYSQL_THD bf_thd, + MYSQL_THD victim_thd, + my_bool signal); + my_bool (*wsrep_thd_order_before_func)(const MYSQL_THD left, const MYSQL_THD right); + void (*wsrep_handle_SR_rollback_func)(MYSQL_THD BF_thd, MYSQL_THD victim_thd); + my_bool (*wsrep_thd_skip_locking_func)(const MYSQL_THD thd); + const char* (*wsrep_get_sr_table_name_func)(); + my_bool (*wsrep_get_debug_func)(); } *wsrep_service; +#define MYSQL_SERVICE_WSREP_INCLUDED +#endif + #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() -#define get_wsrep_drupal_282555_workaround() wsrep_service->get_wsrep_drupal_282555_workaround_func() + +#define MYSQL_SERVICE_WSREP_DYNAMIC_INCLUDED #define get_wsrep_recovery() wsrep_service->get_wsrep_recovery_func() -#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) -#define wsrep_thd_conflict_state(T,S) wsrep_service->wsrep_thd_conflict_state_func(T,S) -#define wsrep_thd_conflict_state_str(T) wsrep_service->wsrep_thd_conflict_state_str_func(T) -#define wsrep_thd_exec_mode(T) wsrep_service->wsrep_thd_exec_mode_func(T) -#define wsrep_thd_exec_mode_str(T) wsrep_service->wsrep_thd_exec_mode_str_func(T) -#define wsrep_thd_get_conflict_state(T) wsrep_service->wsrep_thd_get_conflict_state_func(T) -#define wsrep_thd_is_BF(T,S) wsrep_service->wsrep_thd_is_BF_func(T,S) -#define wsrep_thd_is_wsrep(T) wsrep_service->wsrep_thd_is_wsrep_func(T) #define wsrep_thd_query(T) wsrep_service->wsrep_thd_query_func(T) -#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_set_data_home_dir(A) wsrep_service->wsrep_set_data_home_dir_func(A) - -#define wsrep_debug get_wsrep_debug() -#define wsrep_log_conflicts get_wsrep_log_conflicts() -#define wsrep_certify_nonPK get_wsrep_certify_nonPK() -#define wsrep_load_data_splitting get_wsrep_load_data_splitting() -#define wsrep_drupal_282555_workaround get_wsrep_drupal_282555_workaround() -#define wsrep_recovery get_wsrep_recovery() -#define wsrep_protocol_version get_wsrep_protocol_version() +#define wsrep_thd_is_BF(T,S) wsrep_service->wsrep_thd_is_BF_func(T,S) +#define wsrep_thd_is_aborting(T) wsrep_service->wsrep_thd_is_aborting_func(T) +#define wsrep_thd_is_local(T) wsrep_service->wsrep_thd_is_local_func(T) +#define wsrep_thd_self_abort(T) wsrep_service->wsrep_thd_self_abort_func(T) +#define wsrep_thd_append_key(T,W,N,K) wsrep_service->wsrep_thd_append_key_func(T,W,N,K) +#define wsrep_thd_client_state_str(T) wsrep_service->wsrep_thd_client_state_str_func(T) +#define wsrep_thd_client_mode_str(T) wsrep_service->wsrep_thd_client_mode_str_func(T) +#define wsrep_thd_transaction_state_str(T) wsrep_service->wsrep_thd_transaction_state_str_func(T) +#define wsrep_thd_transaction_id(T) wsrep_service->wsrep_thd_transaction_id_func(T) +#define wsrep_thd_bf_abort(T,T2,S) wsrep_service->wsrep_thd_bf_abort_func(T,T2,S) +#define wsrep_thd_order_before(L,R) wsrep_service->wsrep_thd_order_before_func(L,R) +#define wsrep_handle_SR_rollback(B,V) wsrep_service->wsrep_handle_SR_rollback_func(B,V) +#define wsrep_thd_skip_locking(T) wsrep_service->wsrep_thd_skip_locking_func(T) +#define wsrep_get_sr_table_name() wsrep_service->wsrep_get_sr_table_name_func() +#define wsrep_get_debug() wsrep_service->wsrep_get_debug_func() #else +#define MYSQL_SERVICE_WSREP_STATIC_INCLUDED extern my_bool wsrep_debug; extern my_bool wsrep_log_conflicts; extern my_bool wsrep_certify_nonPK; @@ -176,54 +130,81 @@ extern my_bool wsrep_drupal_282555_workaround; extern my_bool wsrep_recovery; extern long wsrep_protocol_version; -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); -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); -enum wsrep_conflict_state wsrep_thd_conflict_state(MYSQL_THD thd, my_bool sync); -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); -long long wsrep_xid_seqno(const struct xid_t* xid); +extern "C" bool wsrep_consistency_check(MYSQL_THD thd); +bool wsrep_prepare_key_for_innodb(MYSQL_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" const char *wsrep_thd_query(const MYSQL_THD thd); +extern "C" int wsrep_is_wsrep_xid(const void* xid); +extern "C" 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_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); -my_bool get_wsrep_certify_nonPK(); -my_bool get_wsrep_debug(); -my_bool get_wsrep_drupal_282555_workaround(); +extern "C" long long wsrep_thd_trx_seqno(const MYSQL_THD thd); 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_wsrep(MYSQL_THD thd); -struct wsrep *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(); +bool wsrep_thd_ignore_table(MYSQL_THD thd); void wsrep_set_data_home_dir(const char *data_dir); +/* from mysql wsrep-lib */ +#include "my_global.h" +#include "my_pthread.h" + +/* Return true if wsrep is enabled for a thd. This means that + wsrep is enabled globally and the thd has wsrep on */ +extern "C" my_bool wsrep_on(const MYSQL_THD thd); +/* Lock thd wsrep lock */ +extern "C" void wsrep_thd_LOCK(const MYSQL_THD thd); +/* Unlock thd wsrep lock */ +extern "C" void wsrep_thd_UNLOCK(const MYSQL_THD thd); + +/* Return thd client state string */ +extern "C" const char* wsrep_thd_client_state_str(const MYSQL_THD thd); +/* Return thd client mode string */ +extern "C" const char* wsrep_thd_client_mode_str(const MYSQL_THD thd); +/* Return thd transaction state string */ +extern "C" const char* wsrep_thd_transaction_state_str(const MYSQL_THD thd); + +/* Return current transaction id */ +extern "C" query_id_t wsrep_thd_transaction_id(const MYSQL_THD thd); +/* Mark thd own transaction as aborted */ +extern "C" void wsrep_thd_self_abort(MYSQL_THD thd); +/* Return true if thd is in replicating mode */ +extern "C" my_bool wsrep_thd_is_local(const MYSQL_THD thd); +/* Return true if thd is in high priority mode */ +/* todo: rename to is_high_priority() */ +extern "C" my_bool wsrep_thd_is_applying(const MYSQL_THD thd); +/* Return true if thd is in TOI mode */ +extern "C" my_bool wsrep_thd_is_toi(const MYSQL_THD thd); +/* Return true if thd is in replicating TOI mode */ +extern "C" my_bool wsrep_thd_is_local_toi(const MYSQL_THD thd); +/* Return true if thd is in RSU mode */ +extern "C" my_bool wsrep_thd_is_in_rsu(const MYSQL_THD thd); +/* Return true if thd is in BF mode, either high_priority or TOI */ +extern "C" my_bool wsrep_thd_is_BF(const MYSQL_THD thd, my_bool sync); +/* Return true if thd is streaming */ +extern "C" my_bool wsrep_thd_is_SR(const MYSQL_THD thd); +extern "C" void wsrep_handle_SR_rollback(MYSQL_THD BF_thd, MYSQL_THD victim_thd); +/* Return thd retry counter */ +extern "C" int wsrep_thd_retry_counter(const MYSQL_THD thd); +/* BF abort victim_thd */ +extern "C" my_bool wsrep_thd_bf_abort(const MYSQL_THD bf_thd, + MYSQL_THD victim_thd, + my_bool signal); +/* Return true if left thd is ordered before right thd */ +extern "C" my_bool wsrep_thd_order_before(const MYSQL_THD left, const MYSQL_THD right); +/* Return true if thd should skip locking. This means that the thd + is operating on shared resource inside commit order critical section. */ +extern "C" my_bool wsrep_thd_skip_locking(const MYSQL_THD thd); +/* Return true if thd is aborting */ +extern "C" my_bool wsrep_thd_is_aborting(const MYSQL_THD thd); + +struct wsrep_key; +struct wsrep_key_array; +extern "C" int wsrep_thd_append_key(MYSQL_THD thd, + const struct wsrep_key* key, + int n_keys, + enum Wsrep_service_key_type); + +extern const char* wsrep_sr_table_name_full; + +extern "C" const char* wsrep_get_sr_table_name(); + +extern "C" my_bool wsrep_get_debug(); #endif - -#ifdef __cplusplus -} -#endif - -#define MYSQL_SERVICE_WSREP_INCLUDED -#endif - +#endif /* MYSQL_SERVICE_WSREP_INCLUDED */ diff --git a/include/thr_lock.h b/include/thr_lock.h index e6451bf21c4..ee15fd7315d 100644 --- a/include/thr_lock.h +++ b/include/thr_lock.h @@ -168,9 +168,9 @@ void thr_set_lock_wait_callback(void (*before_wait)(void), void (*after_wait)(void)); #ifdef WITH_WSREP - typedef my_bool (* wsrep_thd_is_brute_force_fun)(void *, my_bool); - typedef int (* wsrep_abort_thd_fun)(void *, void *, my_bool); - typedef int (* wsrep_on_fun)(void *); + typedef my_bool (* wsrep_thd_is_brute_force_fun)(const MYSQL_THD, my_bool); + typedef my_bool(* wsrep_abort_thd_fun)(const MYSQL_THD, MYSQL_THD, my_bool); + typedef my_bool (* wsrep_on_fun)(const MYSQL_THD); void wsrep_thr_lock_init( wsrep_thd_is_brute_force_fun bf_fun, wsrep_abort_thd_fun abort_fun, my_bool debug, my_bool convert_LOCK_to_trx, wsrep_on_fun on_fun); diff --git a/include/wsrep.h b/include/wsrep.h index f7a9b6b0231..df8a88e1c69 100644 --- a/include/wsrep.h +++ b/include/wsrep.h @@ -13,11 +13,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#include <my_config.h> - #ifndef WSREP_INCLUDED #define WSREP_INCLUDED +#include <my_config.h> + #ifdef WITH_WSREP #define IF_WSREP(A,B) A #define DBUG_ASSERT_IF_WSREP(A) DBUG_ASSERT(A) @@ -28,12 +28,14 @@ goto wsrep_error_label; #define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_) \ - if (WSREP_ON && WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, \ - table_list_, alter_info_)) \ + if (WSREP(thd) && wsrep_thd_is_local(thd) && \ + wsrep_to_isolation_begin(thd, db_, table_, \ + table_list_, alter_info_)) \ goto wsrep_error_label; -#define WSREP_TO_ISOLATION_END \ - if (WSREP_ON && (WSREP(thd) || (thd && thd->wsrep_exec_mode==TOTAL_ORDER))) \ +#define WSREP_TO_ISOLATION_END \ + if ((WSREP(thd) && wsrep_thd_is_local_toi(thd)) || \ + wsrep_thd_is_in_rsu(thd)) \ wsrep_to_isolation_end(thd); /* @@ -54,19 +56,22 @@ { if (WSREP_CLIENT(thd_) && \ wsrep_sync_wait(thd_, before_)) goto wsrep_error_label; } -#else +#else /* !WITH_WSREP */ + +/* These macros are needed to compile MariaDB without WSREP support + * (e.g. embedded) */ + #define IF_WSREP(A,B) B -#define DBUG_ASSERT_IF_WSREP(A) +//#define DBUG_ASSERT_IF_WSREP(A) #define WSREP_DEBUG(...) -#define WSREP_INFO(...) -#define WSREP_WARN(...) +//#define WSREP_INFO(...) +//#define WSREP_WARN(...) #define WSREP_ERROR(...) #define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) do { } while(0) #define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_) #define WSREP_TO_ISOLATION_END #define WSREP_TO_ISOLATION_BEGIN_WRTCHK(db_, table_, table_list_) #define WSREP_SYNC_WAIT(thd_, before_) - #endif /* WITH_WSREP */ #endif /* WSREP_INCLUDED */ diff --git a/mysql-test/include/check-testcase.test b/mysql-test/include/check-testcase.test index a9c8e13fa7c..39aa3d49d68 100644 --- a/mysql-test/include/check-testcase.test +++ b/mysql-test/include/check-testcase.test @@ -103,5 +103,56 @@ cat_file $datadir.tempfiles.txt; remove_file $datadir.tempfiles.txt; list_files $datadir/mysql #sql*; +# +# Check that SHOW ENGINE INNODB STATUS does not show any active transactions +# We do this only if wsrep provider is loaded, to avoid disturbing any non-Galera MTR tests +# +if (`SELECT COUNT(*)=1 FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'wsrep' AND PLUGIN_STATUS='ACTIVE'`) { + if (`SELECT @@wsrep_on`) { + if (`SELECT COUNT(*) FROM information_schema.innodb_trx WHERE trx_mysql_thread_id != 0`) { + if ($before) { + --echo Before test start. + } + if (!$before) { + --echo After test end. + } + --echo There is one or more active InnoDB transaction(s) when there should be none. Dumping some diagnostics. + + --let $status_locks = `SELECT @@innodb_status_output_locks` + --let $status_output = `SELECT @@innodb_status_output` + --enable_query_log + SET GLOBAL innodb_status_output_locks=ON; + SHOW ENGINE INNODB STATUS; + --disable_query_log + --eval SET GLOBAL innodb_status_output_locks=$status_locks; + --eval SET GLOBAL innodb_status_output=$status_output; + --enable_query_log + + --vertical_results + if ($before) { + --replace_regex /$/ / + } + SELECT * FROM information_schema.processlist; + + if ($before) { + --replace_regex /$/ / + } + SELECT * FROM information_schema.innodb_trx; + + if ($before) { + --replace_regex /$/ / + } + SELECT * FROM information_schema.innodb_locks; + + if ($before) { + --replace_regex /$/ / + } + SELECT * FROM information_schema.innodb_lock_waits; + --horizontal_results + --disable_query_log + } + } +} + --enable_query_log 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_wsrep_enabled.inc b/mysql-test/include/have_wsrep_enabled.inc index 9287369c87c..7eb8b4372cf 100644 --- a/mysql-test/include/have_wsrep_enabled.inc +++ b/mysql-test/include/have_wsrep_enabled.inc @@ -1,7 +1,6 @@ # To be used in a test which requires wsrep plugin to be ACTIVE and enabled # (i.e. wsrep_on=ON). It includes have_wsrep.inc. ---source include/have_wsrep.inc --source include/have_innodb.inc if (`SELECT COUNT(*)=0 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'wsrep_on' AND VARIABLE_VALUE='ON'`) 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/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/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index b5b8a92f1ec..428092a355a 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2896,15 +2896,44 @@ sub mysql_server_start($) { # Save this test case information, so next can examine it $mysqld->{'started_tinfo'}= $tinfo; } + + # 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 + if (wsrep_on($mysqld) && wsrep_is_bootstrap_server($mysqld)) + { + mtr_verbose("Waiting for wsrep bootstrap server to start"); + if ($mysqld->{WAIT}->($mysqld)) + { + return 1; + } + } } sub mysql_server_wait { - my ($mysqld) = @_; + my ($mysqld, $tinfo) = @_; - return not sleep_until_file_created($mysqld->value('pid-file'), - $opt_start_timeout, - $mysqld->{'proc'}, - $warn_seconds); + if (!sleep_until_file_created($mysqld->value('pid-file'), + $opt_start_timeout, + $mysqld->{'proc'}, + $warn_seconds)) + { + $tinfo->{comment}= "Failed to start ".$mysqld->name() . "\n"; + return 1; + } + + if (wsrep_on($mysqld)) + { + mtr_verbose("Waiting for wsrep server " . $mysqld->name() . " to be ready"); + if (!wait_wsrep_ready($tinfo, $mysqld)) + { + return 1; + } + } + + return 0; } sub create_config_file_for_extern { @@ -5408,6 +5437,118 @@ sub stop_servers($$) { } } +# +# run_query_output +# +# Run a query against a server using mysql client. The output of +# the query will be written into outfile. +# +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 +} + + +# +# wsrep_wait_ready +# +# Wait until the server has been joined to the cluster and is +# ready for operation. +# +# RETURN +# 1 Server is ready +# 0 Server didn't transition to ready state within start timeout +# +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_NAME, VARIABLE_VALUE + FROM INFORMATION_SCHEMA.GLOBAL_STATUS + WHERE VARIABLE_NAME = 'wsrep_ready'"; + + for (my $loop= 1; $loop <= $loops; $loop++) + { + # Careful... if MTR runs with option 'verbose' then the + # file contains also SafeProcess verbose output + if (run_query_output($mysqld, $query, $outfile) == 0 && + mtr_grab_file($outfile) =~ /WSREP_READY\s+ON/) + { + unlink($outfile); + return 1; + } + mtr_milli_sleep($sleeptime); + } + + $tinfo->{logfile}= "WSREP did not transition to state READY"; + return 0; +} + +# +# wsrep_is_bootstrap_server +# +# Check if the server is the first one to be started in the +# cluster. +# +# RETURN +# 1 The server is a bootstrap server +# 0 The server is not a bootstrap server +# +sub wsrep_is_bootstrap_server($) { + my $mysqld= shift; + + my $cluster_address= $mysqld->if_exist('wsrep-cluster-address') || + $mysqld->if_exist('wsrep_cluster_address'); + if (defined $cluster_address) + { + return $cluster_address eq "gcomm://" || $cluster_address eq "'gcomm://'"; + } + return 0; +} + +# +# wsrep_on +# +# Check if wsrep has been enabled for a server. +# +# RETURN +# 1 Wsrep has been enabled +# 0 Wsrep is not enabled +# +sub wsrep_on($) { + my $mysqld= shift; + #check if wsrep_on= is set in configuration + if ($mysqld->if_exist('wsrep-on')) { + my $on= "".$mysqld->value('wsrep-on'); + if ($on eq "1" || $on eq "ON") { + return 1; + } + } + return 0; +} + # # start_servers @@ -5427,8 +5568,7 @@ sub start_servers($) { for (all_servers()) { next unless $_->{WAIT} and started($_); - if ($_->{WAIT}->($_)) { - $tinfo->{comment}= "Failed to start ".$_->name() . "\n"; + if ($_->{WAIT}->($_, $tinfo)) { return 1; } } diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 7064df982dd..b179c9d2a63 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -9,13 +9,14 @@ # 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 galera_migrate : MariaDB does not support START SLAVE USER galera_as_master_gtid : Requires MySQL GTID galera_as_master_gtid_change_master : Requires MySQL GTID +galera_as_slave_gtid_replicate_do_db_cc : Requires MySQL GTID galera_as_slave_preordered : wsrep-preordered feature not merged to MariaDB GAL-419 : MDEV-13549 Galera test failures galera_var_notify_cmd : MDEV-13549 Galera test failures @@ -52,3 +53,13 @@ galera.galera_var_reject_queries : assertion in inline_mysql_socket_send query_cache : MDEV-18137: Galera test failure on query_cache galera.galera_autoinc_sst_mariabackup : MDEV-18177 Galera test failure on galera_autoinc_sst_mariabackup galera_gcache_recover_manytrx : MDEV-15740 +galera.galera_ist_mariabackup : Leaves port open +galera.galera_sst_rsync2 : MDEV-18178 Galera test failure on galera_sst_rsync2 +galera.galera_kill_largechanges : MDEV-18179 Galera test failure on galera.galera_kill_largechanges +galera.galera_concurrent_ctas : MDEV-18180 Galera test failure on galera.galera_concurrent_ctas +galera.galera_var_retry_autocommit: MDEV-18181 Galera test failure on galera.galera_var_retry_autocommit +galera.galera_many_tables_nopk : MDEV-18182 Galera test failure on galera.galera_many_tables_nopk +galera.galera_kill_nochanges : MDEV-18280 Galera test failure on galera_split_brain and galera_kill_nochanges +galera.galera_split_brain : MDEV-18280 Galera test failure on galera_split_brain and galera_kill_nochanges +galera.galera_bf_abort_group_commit : MDEV-18282 Galera test failure on galera.galera_bf_abort_group_commit +galera.GCF-1081 : MDEV-18283 Galera test failure on galera.GCF-1081 diff --git a/mysql-test/suite/galera/galera_2nodes.cnf b/mysql-test/suite/galera/galera_2nodes.cnf index b24f3603894..ef8a17a77be 100644 --- a/mysql-test/suite/galera/galera_2nodes.cnf +++ b/mysql-test/suite/galera/galera_2nodes.cnf @@ -2,7 +2,7 @@ !include include/default_mysqld.cnf [mysqld] -wsrep-on=1 +loose-innodb binlog-format=row innodb-autoinc-lock-mode=2 default-storage-engine=innodb @@ -10,20 +10,35 @@ 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-on=1 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-on=1 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 @@ -43,4 +64,3 @@ NODE_MYSOCK_1= @mysqld.1.socket NODE_MYPORT_2= @mysqld.2.port NODE_MYSOCK_2= @mysqld.2.socket - diff --git a/mysql-test/suite/galera/galera_2nodes_as_master.cnf b/mysql-test/suite/galera/galera_2nodes_as_master.cnf index 33bfc475721..4403416b033 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 @@ -62,9 +74,3 @@ 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_SSTPORT_1= @mysqld.1.#sst_port -NODE_SSTPORT_2= @mysqld.2.#sst_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..d1fa7bfbfca 100644 --- a/mysql-test/suite/galera/galera_2nodes_as_slave.cnf +++ b/mysql-test/suite/galera/galera_2nodes_as_slave.cnf @@ -9,17 +9,13 @@ 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 +23,53 @@ 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.3] +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 @@ -69,9 +80,3 @@ NODE_MYSOCK_2= @mysqld.2.socket NODE_MYPORT_3= @mysqld.3.port NODE_MYSOCK_3= @mysqld.3.socket - -NODE_GALERAPORT_2= @mysqld.2.#galera_port -NODE_GALERAPORT_3= @mysqld.3.#galera_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..c84c4b25d2a 100644 --- a/mysql-test/suite/galera/galera_3nodes_as_slave.cnf +++ b/mysql-test/suite/galera/galera_3nodes_as_slave.cnf @@ -8,14 +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 @@ -24,19 +25,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 +49,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 +74,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 @@ -87,11 +105,3 @@ NODE_MYSOCK_3= @mysqld.3.socket NODE_MYPORT_4= @mysqld.4.port NODE_MYSOCK_4= @mysqld.4.socket - -NODE_GALERAPORT_2= @mysqld.2.#galera_port -NODE_GALERAPORT_3= @mysqld.3.#galera_port -NODE_GALERAPORT_4= @mysqld.4.#galera_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..7f59f75b2dc 100644 --- a/mysql-test/suite/galera/galera_4nodes.cnf +++ b/mysql-test/suite/galera/galera_4nodes.cnf @@ -5,50 +5,68 @@ binlog-format=row innodb-autoinc-lock-mode=2 default-storage-engine=innodb -wsrep-on=1 wsrep-provider=@ENV.WSREP_PROVIDER 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 #ist_port=@OPT.port #sst_port=@OPT.port +wsrep-on=1 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 #ist_port=@OPT.port #sst_port=@OPT.port +wsrep-on=1 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] #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port +wsrep-on=1 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] #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port +wsrep-on=1 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 @@ -62,13 +80,3 @@ 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/include/galera_base_port.inc b/mysql-test/suite/galera/include/galera_base_port.inc new file mode 100644 index 00000000000..caf986ee950 --- /dev/null +++ b/mysql-test/suite/galera/include/galera_base_port.inc @@ -0,0 +1,8 @@ +# +# Extract base_port from galera node. +# + +# Convert "... base_port = N; ..." to "N; ..." +--let $s1 = `SELECT SUBSTR(@@wsrep_provider_options, LOCATE('base_port =', @@wsrep_provider_options) + LENGTH('base_port = '))` +# Convert "N; ..." to "N" +--let $_NODE_GALERAPORT = `SELECT SUBSTR('$s1', 1, LOCATE(';', '$s1') - 1)` diff --git a/mysql-test/suite/galera/include/galera_concurrent_test.inc b/mysql-test/suite/galera/include/galera_concurrent_test.inc new file mode 100644 index 00000000000..3d1bc7674a1 --- /dev/null +++ b/mysql-test/suite/galera/include/galera_concurrent_test.inc @@ -0,0 +1,90 @@ +# +# Perform a quick concurrent test on two nodes using a set of predefined statements. +# +# Such tests are not deterministic, so we are hoping to catch assertions, slave apply errors +# and cases where the two nodes diverge +# +# Parameters: +# - $wsrep_trx_fragment_size +# - $count +# - $query_node_1 +# - $query_node_1a (optional) +# - $query_node_2 +# + +if (!$count) { + --let $count = 50; +} + +if (!$node_1a_connected) { + --connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 + --let $node_1a_connected = 1 +} + +--echo Running a concurrent test with the following queries: +--echo $query_node_1 +--echo $query_node_1a +--echo $query_node_2 + +--connection node_1 +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(255)) ENGINE=InnoDB; + +SET SESSION wsrep_sync_wait = 0; +--eval SET SESSION wsrep_trx_fragment_size = $wsrep_trx_fragment_size; + +--connection node_1a +SET SESSION wsrep_sync_wait = 0; +--eval SET SESSION wsrep_trx_fragment_size = $wsrep_trx_fragment_size; + +--connection node_2 +SET SESSION wsrep_sync_wait = 0; +--eval SET SESSION wsrep_trx_fragment_size = $wsrep_trx_fragment_size; + +--disable_query_log +--let $i = `SELECT $count` +while ($i) +{ + --connection node_1 + --send_eval $query_node_1 + + --connection node_1a + if ($query_node_1a) { + --send_eval $query_node_1a + } + + --connection node_2 + --send_eval $query_node_2 + + --connection node_1 + --error 0,ER_QUERY_INTERRUPTED,ER_LOCK_DEADLOCK,ER_DUP_ENTRY + --reap + + --connection node_1a + if ($query_node_1a) { + --error 0,ER_QUERY_INTERRUPTED,ER_LOCK_DEADLOCK,ER_DUP_ENTRY + --reap + } + + --connection node_2 + --error 0,ER_QUERY_INTERRUPTED,ER_LOCK_DEADLOCK,ER_DUP_ENTRY + --reap + --dec $i +} + +SET SESSION wsrep_sync_wait = 15; +--enable_query_log + +--let $diff_servers = 1 2 +--source include/diff_servers.inc + +DROP TABLE t1; + +--let $query_node_1 = "" +--let $query_node_1a = "" +--let $query_node_2 = "" + +--echo Concurrent test end diff --git a/mysql-test/suite/galera/include/galera_dump_sr_table.inc b/mysql-test/suite/galera/include/galera_dump_sr_table.inc new file mode 100644 index 00000000000..48a55006eae --- /dev/null +++ b/mysql-test/suite/galera/include/galera_dump_sr_table.inc @@ -0,0 +1,28 @@ +# +# Dump the contents of the SR table using mysqldump +# + +--let $sr_min = `SELECT MIN(seqno) FROM mysql.wsrep_streaming_log` +--let $sr_max = `SELECT MAX(seqno) FROM mysql.wsrep_streaming_log` + +--let $seqno = $sr_min +while ($seqno <= $sr_max) +{ + --let $sr_fragment_file = $MYSQLTEST_VARDIR/tmp/sr_fragment.log + --exec rm -rf $sr_fragment_file + --disable_query_log + --eval SELECT frag FROM mysql.wsrep_streaming_log WHERE seqno = $seqno INTO DUMPFILE '$sr_fragment_file' + --enable_query_log + + --let $sr_binlog_file = $MYSQLTEST_VARDIR/tmp/sr_binlog.log + --exec rm -rf $sr_binlog_file + + --exec cp std_data/binlog-header.log $sr_binlog_file + --exec cat $sr_fragment_file >> $sr_binlog_file + + --replace_regex /SET TIMESTAMP=[0-9]+/SET TIMESTAMP=<TIMESTAMP>/ /#[0-9]+ +[0-9]+:[0-9]+:[0-9]+/<ISO TIMESTAMP>/ /pseudo_thread_id=[0-9]+/pseudo_thread_id=<PSEUDO_THREAD_ID>/ /thread_id=[0-9]+/thread_id=<QUERY_THREAD_ID>/ /table id [0-9]+/table id <TABLE_ID>/ /mapped to number [0-9]+/mapped to number <TABLE_ID>/ /auto_increment_increment=[0-9]+/auto_increment_increment=<AUTO_INCREMENT_INCREMENT>/ /auto_increment_offset=[0-9]+/auto_increment_offset=<AUTO_INCREMENT_OFFSET>/ /exec_time=[0-9]+/exec_time=<EXEC_TIME>/ + --exec $MYSQL_BINLOG --skip-gtids $sr_binlog_file --base64-output=decode-rows --start-position=120 | grep -v 'SET @' 2>&1 + + --inc $seqno +} + 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_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_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/GAL-480.result b/mysql-test/suite/galera/r/GAL-480.result index 143f48a69e3..8a4f8edcdd6 100644 --- a/mysql-test/suite/galera/r/GAL-480.result +++ b/mysql-test/suite/galera/r/GAL-480.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (f1 CHAR(10), f0 integer) ENGINE=InnoDB; FLUSH TABLE t1 FOR EXPORT; 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..24d4eab67e5 --- /dev/null +++ b/mysql-test/suite/galera/r/GCF-939.result @@ -0,0 +1,13 @@ +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 +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..11a0a7df387 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=ON; 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-286.result b/mysql-test/suite/galera/r/MW-286.result index f3bef6f7516..b3accb1cd9b 100644 --- a/mysql-test/suite/galera/r/MW-286.result +++ b/mysql-test/suite/galera/r/MW-286.result @@ -1,15 +1,24 @@ +connection node_2; +connection node_1; connection node_1; -CREATE TABLE ten (f1 INTEGER) Engine=InnoDB; -INSERT INTO ten VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; -INSERT INTO t1 (f1) SELECT 000000 + (10000 * a1.f1) + (1000 * a2.f1) + (100 * a3.f1) + (10 * a4.f1) + a5.f1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5; -INSERT INTO t1 (f1) SELECT 100000 + (10000 * a1.f1) + (1000 * a2.f1) + (100 * a3.f1) + (10 * a4.f1) + a5.f1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5;; +INSERT INTO t1 (f1) VALUES (1), (2), (3); connection node_2; SET GLOBAL wsrep_desync = TRUE; SET wsrep_on = FALSE; -ALTER TABLE t1 ADD PRIMARY KEY (f1); +SET SESSION debug_sync = "alter_table_inplace_after_lock_upgrade SIGNAL mdl_locked WAIT_FOR mdl_continue"; +ALTER TABLE t1 ADD PRIMARY KEY (f1);; +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_2a; +SET SESSION debug_sync = "now WAIT_FOR mdl_locked"; +connection node_1; +INSERT INTO t1(f1) VALUES (11); +connection node_2a; +SET debug_sync = "now SIGNAL mdl_continue"; +SET debug_sync='RESET'; +connection node_2; +ERROR 70100: Query execution was interrupted SET wsrep_on = TRUE; SET GLOBAL wsrep_desync = FALSE; connection node_1; DROP TABLE t1; -DROP TABLE ten; 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..f4bb018b442 100644 --- a/mysql-test/suite/galera/r/MW-328A.result +++ b/mysql-test/suite/galera/r/MW-328A.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; @@ -14,10 +16,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 +23,22 @@ connection node_1; DROP PROCEDURE proc_update; DROP TABLE t1, t2; CALL mtr.add_suppression("conflict state 3 after post commit"); +connection node_1; +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; +connection node_2; +UPDATE t1 SET j=2 WHERE i=1; +connection node_1; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM t1; +i j +1 2 +connection node_2; +SELECT * FROM t1; +i j +1 2 +connection node_1; +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 e35044d872b..5961d1f3e24 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; INSERT INTO t1 values(0); connection node_1; 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..9f0a77edbbc 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 @@ -153,3 +198,87 @@ f1 p_id f2 1 1 1 DROP TABLE c; DROP TABLE p; +# +# Start of 10.4 tests +# +connection node_1; +CREATE TABLE pf (f1 INTEGER PRIMARY KEY) ENGINE=INNODB; +CREATE TABLE cf ( +f1 INTEGER PRIMARY KEY, +p_id INTEGER, +CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES pf (f1) +); +INSERT INTO pf VALUES (1); +connection node_1; +SET AUTOCOMMIT=ON; +START TRANSACTION; +INSERT INTO cf (f1, p_id) VALUES (10, 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 cf (f1, p_id) VALUES (20, 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; +connection node_2; +SELECT * FROM pf; +f1 +1 +SELECT * FROM cf; +f1 p_id +10 1 +20 1 +DROP TABLE cf; +DROP TABLE pf; +connection node_1; +CREATE TABLE pg (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; +CREATE TABLE cg (f1 INTEGER PRIMARY KEY, p_id INTEGER, +f2 INTEGER, +CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES pg (f1)) ; +INSERT INTO pg VALUES (1, 0); +INSERT INTO pg VALUES (2, 0); +connection node_1; +SET AUTOCOMMIT=ON; +START TRANSACTION; +UPDATE pg 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 cg VALUES (1, 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_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; +connection node_2; +SELECT * FROM pg; +f1 f2 +1 1 +2 0 +SELECT * FROM cg; +f1 p_id f2 +1 1 0 +DROP TABLE cg; +DROP TABLE pg; diff --git a/mysql-test/suite/galera/r/MW-388.result b/mysql-test/suite/galera/r/MW-388.result index a2cf02712bb..3e532b3e12d 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 () @@ -18,7 +20,7 @@ connection node_1a; SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; connection node_1; SET SESSION wsrep_sync_wait = 0; -SET SESSION DEBUG_SYNC = 'wsrep_after_replication SIGNAL wsrep_after_replication_reached WAIT_FOR wsrep_after_replication_continue'; +SET SESSION DEBUG_SYNC = 'wsrep_after_certification SIGNAL wsrep_after_certification_reached WAIT_FOR wsrep_after_certification_continue'; CALL insert_proc ();; connection node_1a; SET SESSION DEBUG_SYNC = "now WAIT_FOR wsrep_after_replication_reached"; @@ -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..537e648df6b 100644 --- a/mysql-test/suite/galera/r/MW-416.result +++ b/mysql-test/suite/galera/r/MW-416.result @@ -109,6 +109,5 @@ mtr mysql performance_schema test -SHOW GLOBAL STATUS LIKE 'wsrep_replicated'; -Variable_name Value -wsrep_replicated 3 +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..a5ab0b19718 100644 --- a/mysql-test/suite/galera/r/galera#500.result +++ b/mysql-test/suite/galera/r/galera#500.result @@ -1,10 +1,18 @@ +connection node_2; +connection node_1; +connection node_1; +connection node_2; +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#505.result b/mysql-test/suite/galera/r/galera#505.result index 8d3e3ec072a..bc7eb3b9ed4 100644 --- a/mysql-test/suite/galera/r/galera#505.result +++ b/mysql-test/suite/galera/r/galera#505.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; SET SESSION wsrep_sync_wait=0; SET SESSION wsrep_sync_wait=DEFAULT; diff --git a/mysql-test/suite/galera/r/galera_FK_duplicate_client_insert.result b/mysql-test/suite/galera/r/galera_FK_duplicate_client_insert.result index 3eb638ca49a..5ae577a6323 100644 --- a/mysql-test/suite/galera/r/galera_FK_duplicate_client_insert.result +++ b/mysql-test/suite/galera/r/galera_FK_duplicate_client_insert.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; CREATE TABLE user(id int primary key, j int) ENGINE=InnoDB; CREATE TABLE user_session(id int primary key, fk1 int, fk2 int) ENGINE=InnoDB; alter table user_session add foreign key (fk1) references user(id); diff --git a/mysql-test/suite/galera/r/galera_admin.result b/mysql-test/suite/galera/r/galera_admin.result index e52bf8ccca3..01e2aac16b2 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.result b/mysql-test/suite/galera/r/galera_as_slave.result index 9ccb5106234..391ceecd509 100644 --- a/mysql-test/suite/galera/r/galera_as_slave.result +++ b/mysql-test/suite/galera/r/galera_as_slave.result @@ -1,12 +1,14 @@ -connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; connection node_2; -START SLAVE; connection node_1; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_2; +START SLAVE; +connection node_3; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES(1); connection node_2; 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; COUNT(*) = 2 1 @@ -15,10 +17,10 @@ connection node_2; SELECT COUNT(*) = 3 FROM t1; COUNT(*) = 3 1 -connection node_1; +connection node_3; DROP TABLE t1; connection node_2; STOP SLAVE; RESET SLAVE ALL; -connection node_1; +connection node_3; RESET MASTER; 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..6ac51f44950 100644 --- a/mysql-test/suite/galera/r/galera_as_slave_autoinc.result +++ b/mysql-test/suite/galera/r/galera_as_slave_autoinc.result @@ -1,7 +1,9 @@ -connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; connection node_2; -START SLAVE; connection node_1; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_2; +START SLAVE; +connection node_3; SET SESSION binlog_format='STATEMENT'; CREATE TABLE t1 ( i int(11) NOT NULL AUTO_INCREMENT, @@ -60,7 +62,7 @@ binlog_format ROW show variables like 'auto_increment_increment'; Variable_name Value auto_increment_increment 2 -connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_1; select * from t1; i c 1 dummy_text @@ -79,10 +81,10 @@ binlog_format ROW show variables like 'auto_increment_increment'; Variable_name Value auto_increment_increment 2 -connection node_1; +connection node_3; DROP TABLE t1; connection node_2; STOP SLAVE; RESET SLAVE ALL; -connection node_1; +connection node_3; RESET MASTER; 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..180b72bf729 100644 --- a/mysql-test/suite/galera/r/galera_as_slave_gtid.result +++ b/mysql-test/suite/galera/r/galera_as_slave_gtid.result @@ -1,7 +1,9 @@ -connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; connection node_2; -START SLAVE; connection node_1; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_2; +START SLAVE; +connection node_3; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES(1); SELECT LENGTH(@@global.gtid_binlog_state) > 1; @@ -10,15 +12,15 @@ LENGTH(@@global.gtid_binlog_state) > 1 connection node_2; gtid_binlog_state_equal 1 -connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_1; SELECT COUNT(*) = 1 FROM t1; COUNT(*) = 1 1 gtid_binlog_state_equal 1 -connection node_1; -DROP TABLE t1; connection node_3; +DROP TABLE t1; +connection node_1; connection node_2; STOP SLAVE; RESET SLAVE ALL; 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..9589d319991 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_as_slave_gtid_replicate_do_db.result @@ -0,0 +1,159 @@ +connection node_2; +connection node_1; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_1; +SET global wsrep_on=OFF; +RESET MASTER; +SET global wsrep_on=ON; +connection node_3; +RESET MASTER; +connection node_2; +SET global wsrep_on=OFF; +RESET MASTER; +SET global wsrep_on=ON; +START SLAVE; +connection node_3; +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 3 371 GTID 0-3-1 +master-bin.000001 371 Query 3 458 CREATE SCHEMA test1 +master-bin.000001 458 Gtid 3 500 GTID 0-3-3 +master-bin.000001 500 Query 3 647 use `test1`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY,f2 CHAR(5) DEFAULT 'abc') ENGINE=InnoDB +master-bin.000001 647 Gtid 3 689 BEGIN GTID 0-3-5 +master-bin.000001 689 Annotate_rows 3 748 INSERT INTO test1.t1 (f1) VALUES (1) +master-bin.000001 748 Table_map 3 797 table_id: ### (test1.t1) +master-bin.000001 797 Write_rows_v1 3 839 table_id: ### flags: STMT_END_F +master-bin.000001 839 Xid 3 870 COMMIT /* xid=### */ +master-bin.000001 870 Gtid 3 912 BEGIN GTID 0-3-7 +master-bin.000001 912 Annotate_rows 3 971 INSERT INTO test1.t1 (f1) VALUES (2) +master-bin.000001 971 Table_map 3 1020 table_id: ### (test1.t1) +master-bin.000001 1020 Write_rows_v1 3 1062 table_id: ### flags: STMT_END_F +master-bin.000001 1062 Xid 3 1093 COMMIT /* xid=### */ +master-bin.000001 1093 Gtid 3 1135 BEGIN GTID 0-3-9 +master-bin.000001 1135 Annotate_rows 3 1194 INSERT INTO test1.t1 (f1) VALUES (3) +master-bin.000001 1194 Table_map 3 1243 table_id: ### (test1.t1) +master-bin.000001 1243 Write_rows_v1 3 1285 table_id: ### flags: STMT_END_F +master-bin.000001 1285 Xid 3 1316 COMMIT /* xid=### */ +master-bin.000001 1316 Gtid 3 1358 BEGIN GTID 0-3-12 +master-bin.000001 1358 Annotate_rows 3 1451 UPDATE test1.t1, test2.t1 SET test1.t1.f2 = 'klm', test2.t1.f2 = 'xyz' +master-bin.000001 1451 Table_map 3 1500 table_id: ### (test1.t1) +master-bin.000001 1500 Update_rows_v1 3 1588 table_id: ### flags: STMT_END_F +master-bin.000001 1588 Xid 3 1619 COMMIT /* xid=### */ +master-bin.000001 1619 Gtid 3 1661 BEGIN GTID 0-3-13 +master-bin.000001 1661 Annotate_rows 3 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 3 1844 table_id: ### (test1.t1) +master-bin.000001 1844 Delete_rows_v1 3 1886 table_id: ### flags: STMT_END_F +master-bin.000001 1886 Xid 3 1917 COMMIT /* xid=### */ +master-bin.000001 1917 Gtid 3 1959 BEGIN GTID 0-3-15 +master-bin.000001 1959 Annotate_rows 3 2020 INSERT INTO test1.t1 (f1) VALUES (111) +master-bin.000001 2020 Table_map 3 2069 table_id: ### (test1.t1) +master-bin.000001 2069 Write_rows_v1 3 2111 table_id: ### flags: STMT_END_F +master-bin.000001 2111 Annotate_rows 3 2172 INSERT INTO test1.t1 (f1) VALUES (222) +master-bin.000001 2172 Table_map 3 2221 table_id: ### (test1.t1) +master-bin.000001 2221 Write_rows_v1 3 2263 table_id: ### flags: STMT_END_F +master-bin.000001 2263 Xid 3 2294 COMMIT /* xid=### */ +master-bin.000001 2294 Gtid 3 2336 BEGIN GTID <effective_uuid> +master-bin.000001 2336 Annotate_rows 3 2397 INSERT INTO test1.t1 (f1) VALUES (333) +master-bin.000001 2397 Table_map 3 2446 table_id: ### (test1.t1) +master-bin.000001 2446 Write_rows_v1 3 2488 table_id: ### flags: STMT_END_F +master-bin.000001 2488 Xid 3 2519 COMMIT /* xid=### */ +connection node_1; +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 1 285 [] +master-bin.000001 285 Binlog_checkpoint 1 329 master-bin.000001 +master-bin.000001 329 Gtid 3 371 GTID 0-3-1 +master-bin.000001 371 Query 3 458 CREATE SCHEMA test1 +master-bin.000001 458 Gtid 3 500 GTID 0-3-2 +master-bin.000001 500 Query 3 647 use `test1`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY,f2 CHAR(5) DEFAULT 'abc') ENGINE=InnoDB +master-bin.000001 647 Gtid 3 689 BEGIN GTID 0-3-3 +master-bin.000001 689 Annotate_rows 3 748 INSERT INTO test1.t1 (f1) VALUES (1) +master-bin.000001 748 Table_map 3 797 table_id: ### (test1.t1) +master-bin.000001 797 Write_rows_v1 3 839 table_id: ### flags: STMT_END_F +master-bin.000001 839 Xid 3 870 COMMIT /* xid=### */ +master-bin.000001 870 Gtid 3 912 BEGIN GTID 0-3-4 +master-bin.000001 912 Annotate_rows 3 971 INSERT INTO test1.t1 (f1) VALUES (2) +master-bin.000001 971 Table_map 3 1020 table_id: ### (test1.t1) +master-bin.000001 1020 Write_rows_v1 3 1062 table_id: ### flags: STMT_END_F +master-bin.000001 1062 Xid 3 1093 COMMIT /* xid=### */ +master-bin.000001 1093 Gtid 3 1135 BEGIN GTID 0-3-5 +master-bin.000001 1135 Annotate_rows 3 1194 INSERT INTO test1.t1 (f1) VALUES (3) +master-bin.000001 1194 Table_map 3 1243 table_id: ### (test1.t1) +master-bin.000001 1243 Write_rows_v1 3 1285 table_id: ### flags: STMT_END_F +master-bin.000001 1285 Xid 3 1316 COMMIT /* xid=### */ +master-bin.000001 1316 Gtid 3 1358 BEGIN GTID 0-3-6 +master-bin.000001 1358 Annotate_rows 3 1451 UPDATE test1.t1, test2.t1 SET test1.t1.f2 = 'klm', test2.t1.f2 = 'xyz' +master-bin.000001 1451 Table_map 3 1500 table_id: ### (test1.t1) +master-bin.000001 1500 Update_rows_v1 3 1588 table_id: ### flags: STMT_END_F +master-bin.000001 1588 Xid 3 1619 COMMIT /* xid=### */ +master-bin.000001 1619 Gtid 3 1661 BEGIN GTID 0-3-7 +master-bin.000001 1661 Annotate_rows 3 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 3 1844 table_id: ### (test1.t1) +master-bin.000001 1844 Delete_rows_v1 3 1886 table_id: ### flags: STMT_END_F +master-bin.000001 1886 Xid 3 1917 COMMIT /* xid=### */ +master-bin.000001 1917 Gtid 3 1959 BEGIN GTID 0-3-8 +master-bin.000001 1959 Annotate_rows 3 2020 INSERT INTO test1.t1 (f1) VALUES (111) +master-bin.000001 2020 Table_map 3 2069 table_id: ### (test1.t1) +master-bin.000001 2069 Write_rows_v1 3 2111 table_id: ### flags: STMT_END_F +master-bin.000001 2111 Annotate_rows 3 2172 INSERT INTO test1.t1 (f1) VALUES (222) +master-bin.000001 2172 Table_map 3 2221 table_id: ### (test1.t1) +master-bin.000001 2221 Write_rows_v1 3 2263 table_id: ### flags: STMT_END_F +master-bin.000001 2263 Xid 3 2294 COMMIT /* xid=### */ +master-bin.000001 2294 Gtid 3 2336 BEGIN GTID 0-3-9 +master-bin.000001 2336 Annotate_rows 3 2397 INSERT INTO test1.t1 (f1) VALUES (333) +master-bin.000001 2397 Table_map 3 2446 table_id: ### (test1.t1) +master-bin.000001 2446 Write_rows_v1 3 2488 table_id: ### flags: STMT_END_F +master-bin.000001 2488 Xid 3 2519 COMMIT /* xid=### */ +include/diff_servers.inc [servers=1 2] +connection node_1; +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_3; +DROP SCHEMA test1; +DROP SCHEMA test2; +connection node_1; +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..fefc988d9d4 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,5 @@ 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; RESET MASTER; diff --git a/mysql-test/suite/galera/r/galera_autoinc_sst_mariabackup.result b/mysql-test/suite/galera/r/galera_autoinc_sst_mariabackup.result index 91f45c93257..7c98b3e85ed 100644 --- a/mysql-test/suite/galera/r/galera_autoinc_sst_mariabackup.result +++ b/mysql-test/suite/galera/r/galera_autoinc_sst_mariabackup.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_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..2a2ddd519f4 --- /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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..fa2a5c373f2 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_bf_abort_shutdown.result @@ -0,0 +1,12 @@ +connection node_2; +connection node_1; +connection node_1; +connection node_2; +connection node_1; +CREATE TABLE t1 (f1 INT PRIMARY KEY); +connection node_2; +SET DEBUG_SYNC = 'wsrep_before_certification 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_background_statistics.result b/mysql-test/suite/galera/r/galera_bf_background_statistics.result index c2c3fce2b14..a8c8842b8e1 100644 --- a/mysql-test/suite/galera/r/galera_bf_background_statistics.result +++ b/mysql-test/suite/galera/r/galera_bf_background_statistics.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; SELECT @@innodb_stats_persistent; @@innodb_stats_persistent 1 @@ -27,7 +29,7 @@ SELECT SLEEP(1000);; connection node_1; ALTER TABLE t1 CHANGE f2 f2 INTEGER NOT NULL DEFAULT 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_commit_empty.result b/mysql-test/suite/galera/r/galera_commit_empty.result new file mode 100644 index 00000000000..75b94c54b1e --- /dev/null +++ b/mysql-test/suite/galera/r/galera_commit_empty.result @@ -0,0 +1,15 @@ +connection node_2; +connection node_1; +START TRANSACTION; +COMMIT; +START TRANSACTION; +COMMIT; +START TRANSACTION READ ONLY; +COMMIT; +START TRANSACTION; +COMMIT; +START TRANSACTION; +START TRANSACTION; +COMMIT; +wsrep_last_committed_diff +1 diff --git a/mysql-test/suite/galera/r/galera_concurrent_ctas.result b/mysql-test/suite/galera/r/galera_concurrent_ctas.result index 8a3ac1ae0d3..39c55277c52 100644 --- a/mysql-test/suite/galera/r/galera_concurrent_ctas.result +++ b/mysql-test/suite/galera/r/galera_concurrent_ctas.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; disconnect node_2; disconnect node_1; # End of test 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 6871ec6d56b..20ea590e2e5 100644 --- a/mysql-test/suite/galera/r/galera_defaults.result +++ b/mysql-test/suite/galera/r/galera_defaults.result @@ -1,6 +1,8 @@ -SELECT COUNT(*) = 43 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%'; -COUNT(*) = 43 -0 +connection node_2; +connection node_1; +SELECT COUNT(*) `expect 48` FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%'; +expect 48 +48 SELECT VARIABLE_NAME, VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%' @@ -31,6 +33,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,8 +50,11 @@ 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 +WSREP_TRX_FRAGMENT_SIZE 0 +WSREP_TRX_FRAGMENT_UNIT bytes 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_encrypt_tmp_files.result b/mysql-test/suite/galera/r/galera_encrypt_tmp_files.result index 38480d186ba..fdfca3316b1 100644 --- a/mysql-test/suite/galera/r/galera_encrypt_tmp_files.result +++ b/mysql-test/suite/galera/r/galera_encrypt_tmp_files.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_enum.result b/mysql-test/suite/galera/r/galera_enum.result index a2a6317e2a0..40fc6931f6a 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(*) FROM t1 WHERE f1 = 'three'; COUNT(*) 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 a155a410a45..146833fc3c8 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..2342643e745 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; @@ -22,7 +24,7 @@ connection node_2; SET SESSION lock_wait_timeout = 1; SET SESSION innodb_lock_wait_timeout=1; SET SESSION wait_timeout=1; -INSERT INTO t2 VALUES (2); +INSERT INTO t1 VALUES (2); ERROR HY000: Lock wait timeout exceeded; try restarting transaction connection node_2a; UNLOCK TABLES; 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.result b/mysql-test/suite/galera/r/galera_gcache_recover.result index d3ba06c1333..819c595ece3 100644 --- a/mysql-test/suite/galera/r/galera_gcache_recover.result +++ b/mysql-test/suite/galera/r/galera_gcache_recover.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_sync_wait = 0; 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 588af5668bb..a0d128f5fa3 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 @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; SET SESSION wsrep_sync_wait = 0; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 LONGBLOB) ENGINE=InnoDB; connection node_2; @@ -21,6 +23,6 @@ include/diff_servers.inc [servers=1 2] connection node_1; 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] connection node_2; 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_fragment.result b/mysql-test/suite/galera/r/galera_gcs_fragment.result index 0c9c1819f60..bdd749047ee 100644 --- a/mysql-test/suite/galera/r/galera_gcs_fragment.result +++ b/mysql-test/suite/galera/r/galera_gcs_fragment.result @@ -1,24 +1,37 @@ +connection node_2; +connection node_1; +connection node_1; +connection node_2; CREATE TABLE t1 (f1 INT PRIMARY KEY, f2 TEXT); +connection node_2; SET GLOBAL wsrep_cluster_address=''; +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; SET SESSION wsrep_sync_wait=0; SET GLOBAL wsrep_provider_options = 'dbug=d,gcs_core_after_frag_send'; +connection node_1; SET SESSION wsrep_retry_autocommit=0; INSERT INTO t1 VALUES (1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); +connection node_1a; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_2; SET SESSION wsrep_on = 0; SET SESSION wsrep_on = 1; INSERT INTO t1 VALUES (2, "bbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); +connection node_1a; SET GLOBAL wsrep_provider_options = 'signal=gcs_core_after_frag_send'; -ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +connection node_1; +ERROR HY000: Got error 6 "No such device or address" during COMMIT INSERT INTO t1 VALUES (3, "cccccaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); SELECT * FROM t1; f1 f2 2 bbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 3 cccccaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +connection node_2; SELECT * FROM t1; f1 f2 2 bbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 3 cccccaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +connection node_1; DROP TABLE t1; 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..7a3048231af 100644 --- a/mysql-test/suite/galera/r/galera_gtid_slave.result +++ b/mysql-test/suite/galera/r/galera_gtid_slave.result @@ -1,7 +1,9 @@ -connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; connection node_2; -START SLAVE; connection node_1; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_2; +START SLAVE; +connection node_3; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES(1); @@ -11,27 +13,31 @@ insert into t2 values(22); commit; SELECT @@global.gtid_binlog_state; @@global.gtid_binlog_state -1-1-4 +2-3-4 connection node_2; INSERT INTO t1 VALUES(2); INSERT INTO t1 VALUES(3); SELECT @@global.gtid_binlog_state; @@global.gtid_binlog_state -1-1-4,2-2-2 -connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +0-2-2,2-3-4 +connection node_1; INSERT INTO t1 VALUES(4); SELECT @@global.gtid_binlog_state; @@global.gtid_binlog_state -1-1-4,2-2-2,2-3-3 -connection node_1; +1-1-1,2-3-4,2-2-6 +connection node_3; DROP TABLE t1,t2; connection node_2; -connection node_3; +connection node_1; connection node_2; STOP SLAVE; RESET SLAVE ALL; +SET GLOBAL wsrep_on=OFF; reset master; -connection node_3; -reset master; +SET GLOBAL wsrep_on=ON; connection node_1; +SET GLOBAL wsrep_on=OFF; +reset master; +SET GLOBAL wsrep_on=ON; +connection node_3; reset master; 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 380a0235ac2..7c5519af495 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-3-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-3-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-3-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-1-2,2-3-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-1-3,2-3-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-1-7,0-2-8,2-3-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,31 +134,35 @@ 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-1-7,0-2-11,2-3-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-1-3,2-3-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; +set global wsrep_on=ON; set global gtid_slave_pos=""; +#Connection 1 +connection node_1; +set global wsrep_on=OFF; reset master; +set global wsrep_on=ON; #Connection 3 connection node_3; reset master; -#Connection 1 -connection node_1; -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 481a85711be..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,3 +1,5 @@ +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; diff --git a/mysql-test/suite/galera/r/galera_ist_mariabackup,debug.rdiff b/mysql-test/suite/galera/r/galera_ist_mariabackup,debug.rdiff index 9684e290778..fe54c515395 100644 --- a/mysql-test/suite/galera/r/galera_ist_mariabackup,debug.rdiff +++ b/mysql-test/suite/galera/r/galera_ist_mariabackup,debug.rdiff @@ -1,6 +1,6 @@ ---- r/galera_ist_mariabackup.result 2018-11-21 22:30:21.968817468 +0200 -+++ r/galera_ist_mariabackup.reject 2018-11-22 09:16:27.832601754 +0200 -@@ -285,3 +285,111 @@ +--- galera_ist_mariabackup.result 2018-12-11 13:33:56.728535840 +0100 ++++ galera_ist_mariabackup.reject 2018-12-11 13:37:40.572535840 +0100 +@@ -290,3 +290,111 @@ DROP TABLE t1; COMMIT; SET AUTOCOMMIT=ON; diff --git a/mysql-test/suite/galera/r/galera_ist_mariabackup.result b/mysql-test/suite/galera/r/galera_ist_mariabackup.result index 8a7c02ab1b6..13f7d898a59 100644 --- a/mysql-test/suite/galera/r/galera_ist_mariabackup.result +++ b/mysql-test/suite/galera/r/galera_ist_mariabackup.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 @@ -47,6 +49,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'); diff --git a/mysql-test/suite/galera/r/galera_ist_mariabackup_innodb_flush_logs.result b/mysql-test/suite/galera/r/galera_ist_mariabackup_innodb_flush_logs.result index 7813b5a58fc..99b9c8d6c1b 100644 --- a/mysql-test/suite/galera/r/galera_ist_mariabackup_innodb_flush_logs.result +++ b/mysql-test/suite/galera/r/galera_ist_mariabackup_innodb_flush_logs.result @@ -1,3 +1,5 @@ +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; diff --git a/mysql-test/suite/galera/r/galera_ist_mysqldump.result b/mysql-test/suite/galera/r/galera_ist_mysqldump.result index 296ecc2adc7..222eb7704e8 100644 --- a/mysql-test/suite/galera/r/galera_ist_mysqldump.result +++ b/mysql-test/suite/galera/r/galera_ist_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"); @@ -210,3 +212,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_ist_progress.result b/mysql-test/suite/galera/r/galera_ist_progress.result index ed36a217624..9fc7febbea5 100644 --- a/mysql-test/suite/galera/r/galera_ist_progress.result +++ b/mysql-test/suite/galera/r/galera_ist_progress.result @@ -1,10 +1,6 @@ -connection node_2; SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1'; -connection node_1; -connection node_2; SET SESSION wsrep_on = OFF; SET SESSION wsrep_on = ON; -connection node_1; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (2); @@ -16,13 +12,8 @@ INSERT INTO t1 VALUES (7); INSERT INTO t1 VALUES (8); INSERT INTO t1 VALUES (9); INSERT INTO t1 VALUES (10); -connection node_2; SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0'; -connection node_1; -connection node_2; -connection node_1; include/assert_grep.inc [Receiving IST: 11 writesets, seqnos] include/assert_grep.inc [Receiving IST\.\.\. 0\.0% \( 0/11 events\) complete] include/assert_grep.inc [Receiving IST\.\.\.100\.0% \(11/11 events\) complete] -connection node_1; DROP TABLE t1; 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 8a7c02ab1b6..13f7d898a59 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 @@ -47,6 +49,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'); diff --git a/mysql-test/suite/galera/r/galera_kill_ddl.result b/mysql-test/suite/galera/r/galera_kill_ddl.result index b11353fcbcc..9d66140465c 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; call mtr.add_suppression("WSREP: Last Applied Action message in non-primary configuration from member .*"); connection node_1; SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; diff --git a/mysql-test/suite/galera/r/galera_kill_largechanges.result b/mysql-test/suite/galera/r/galera_kill_largechanges.result index f4de101fef8..a04729d2c87 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; call mtr.add_suppression("WSREP: Last Applied Action message in non-primary configuration from member .*"); connection node_1; SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; diff --git a/mysql-test/suite/galera/r/galera_kill_smallchanges.result b/mysql-test/suite/galera/r/galera_kill_smallchanges.result index 2ee291004b0..206591bbebe 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; call mtr.add_suppression("WSREP: Last Applied Action message in non-primary configuration from member .*"); connection node_1; SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true'; 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 0d8688e3709..963d3552252 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); @@ -131,5 +133,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..26771dc3c24 100644 --- a/mysql-test/suite/galera/r/galera_many_rows.result +++ b/mysql-test/suite/galera/r/galera_many_rows.result @@ -1,3 +1,7 @@ +connection node_2; +connection node_1; +connection node_1; +connection node_2; connection node_1; SET SESSION innodb_lock_wait_timeout=600; SET SESSION lock_wait_timeout=600; @@ -35,6 +39,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_mdev_15611.result b/mysql-test/suite/galera/r/galera_mdev_15611.result index 9ea1684494a..5461f8f03fb 100644 --- a/mysql-test/suite/galera/r/galera_mdev_15611.result +++ b/mysql-test/suite/galera/r/galera_mdev_15611.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 ( id int primary key 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..48625b3ba4a 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; @@ -30,7 +32,7 @@ COUNT(*) = 1 SELECT COUNT(*) = 1 FROM t2; COUNT(*) = 1 1 -SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'committed%'; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%committed%'; COUNT(*) = 2 1 SET GLOBAL wsrep_slave_threads = 1;; 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..d2e09d7084f 100644 --- a/mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result +++ b/mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result @@ -1,5 +1,7 @@ +connection node_2; +connection node_1; connection node_1; -CREATE TABLE ten (f1 INTEGER); +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; connection node_2; @@ -11,18 +13,26 @@ INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;; connection node_2; INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;; connection node_1; +SELECT COUNT(*) FROM t1; +COUNT(*) +30000 +SELECT COUNT(DISTINCT f1) FROM t1; +COUNT(DISTINCT f1) +30000 connection node_1a; -connection node_2; SELECT COUNT(*) FROM t1; COUNT(*) 30000 SELECT COUNT(DISTINCT f1) FROM t1; COUNT(DISTINCT f1) 30000 -SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE -USER = 'system user' AND STATE NOT LIKE 'InnoDB%'; +connection node_2; +SELECT COUNT(*) FROM t1; COUNT(*) -3 +30000 +SELECT COUNT(DISTINCT f1) FROM t1; +COUNT(DISTINCT f1) +30000 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..09a415d47eb 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); @@ -12,7 +14,7 @@ COUNT(*) = 20000 SELECT COUNT(DISTINCT f1) = 20000 FROM t1; COUNT(DISTINCT f1) = 20000 1 -SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'committed%'; +SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'wsrep applier committed%'; COUNT(*) = 4 1 connection default; 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_pc_recovery.result b/mysql-test/suite/galera/r/galera_pc_recovery.result new file mode 100644 index 00000000000..17a43d17211 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_pc_recovery.result @@ -0,0 +1,37 @@ +connection node_2; +connection node_1; +connection node_1; +connection node_2; +connection node_1; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +connection node_2; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +connection node_1; +SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +VARIABLE_VALUE = 'Primary' +1 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +connection node_2; +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 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +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/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 6f546b32819..b84f25e9929 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_roles.result b/mysql-test/suite/galera/r/galera_roles.result index bef89acfc92..b1124b597c5 100644 --- a/mysql-test/suite/galera/r/galera_roles.result +++ b/mysql-test/suite/galera/r/galera_roles.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; # # Testing CREATE/GRANT role # 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_mariabackup.result b/mysql-test/suite/galera/r/galera_sst_mariabackup.result index fdb5883b590..4fdc283b286 100644 --- a/mysql-test/suite/galera/r/galera_sst_mariabackup.result +++ b/mysql-test/suite/galera/r/galera_sst_mariabackup.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 diff --git a/mysql-test/suite/galera/r/galera_sst_mariabackup_data_dir.result b/mysql-test/suite/galera/r/galera_sst_mariabackup_data_dir.result index fdb5883b590..4fdc283b286 100644 --- a/mysql-test/suite/galera/r/galera_sst_mariabackup_data_dir.result +++ b/mysql-test/suite/galera/r/galera_sst_mariabackup_data_dir.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 diff --git a/mysql-test/suite/galera/r/galera_sst_mariabackup_encrypt_with_key.result b/mysql-test/suite/galera/r/galera_sst_mariabackup_encrypt_with_key.result index 990e0a29506..409da775d9a 100644 --- a/mysql-test/suite/galera/r/galera_sst_mariabackup_encrypt_with_key.result +++ b/mysql-test/suite/galera/r/galera_sst_mariabackup_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_sst_mariabackup_table_options.result b/mysql-test/suite/galera/r/galera_sst_mariabackup_table_options.result index 9180ed5e421..568c06de94c 100644 --- a/mysql-test/suite/galera/r/galera_sst_mariabackup_table_options.result +++ b/mysql-test/suite/galera/r/galera_sst_mariabackup_table_options.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; connection node_2; Performing State Transfer on a server that starts from a clean var directory diff --git a/mysql-test/suite/galera/r/galera_sst_mysqldump,debug.rdiff b/mysql-test/suite/galera/r/galera_sst_mysqldump,debug.rdiff index 3eadee615ed..2978411c8f7 100644 --- a/mysql-test/suite/galera/r/galera_sst_mysqldump,debug.rdiff +++ b/mysql-test/suite/galera/r/galera_sst_mysqldump,debug.rdiff @@ -1,6 +1,22 @@ ---- galera_sst_mysqldump.result -+++ galera_sst_mysqldump,debug.reject -@@ -388,6 +388,114 @@ +--- galera_sst_mysqldump.result 2018-11-29 23:54:03.663607613 +0100 ++++ galera_sst_mysqldump,debug.reject 2018-11-29 23:55:42.377562815 +0100 +@@ -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'); + 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 @@ DROP TABLE t1; COMMIT; SET AUTOCOMMIT=ON; diff --git a/mysql-test/suite/galera/r/galera_sst_mysqldump,release.rdiff b/mysql-test/suite/galera/r/galera_sst_mysqldump,release.rdiff new file mode 100644 index 00000000000..3e8fee1b098 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sst_mysqldump,release.rdiff @@ -0,0 +1,18 @@ +--- suite/galera/r/galera_sst_mysqldump.result 2018-12-20 14:22:41.730134062 +0100 ++++ suite/galera/r/galera_sst_mysqldump.reject 2019-01-16 22:18:44.139781857 +0100 +@@ -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'); + 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'); diff --git a/mysql-test/suite/galera/r/galera_sst_mysqldump.result b/mysql-test/suite/galera/r/galera_sst_mysqldump.result index 5c530c32ce6..4ed679ba477 100644 --- a/mysql-test/suite/galera/r/galera_sst_mysqldump.result +++ b/mysql-test/suite/galera/r/galera_sst_mysqldump.result @@ -400,3 +400,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..d41d0d34e75 100644 --- a/mysql-test/suite/galera/r/galera_sst_rsync.result +++ b/mysql-test/suite/galera/r/galera_sst_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 shut down cleanly and restarted diff --git a/mysql-test/suite/galera/r/galera_sst_rsync2,debug.rdiff b/mysql-test/suite/galera/r/galera_sst_rsync2,debug.rdiff index 525156d88da..8ffe51c0cc3 100644 --- a/mysql-test/suite/galera/r/galera_sst_rsync2,debug.rdiff +++ b/mysql-test/suite/galera/r/galera_sst_rsync2,debug.rdiff @@ -1,6 +1,12 @@ ---- suite/galera/r/galera_sst_rsync2.result 2018-09-12 13:09:35.352229478 +0200 -+++ suite/galera/r/galera_sst_rsync2,debug.reject 2018-09-12 17:00:51.601974979 +0200 -@@ -286,3 +286,111 @@ +--- galera_sst_rsync2.result 2018-11-29 17:57:53.288606346 +0100 ++++ galera_sst_rsync2,debug.reject 2018-11-29 18:00:01.172512000 +0100 +@@ -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,3 +288,111 @@ DROP TABLE t1; COMMIT; SET AUTOCOMMIT=ON; diff --git a/mysql-test/suite/galera/r/galera_sst_rsync_data_dir.result b/mysql-test/suite/galera/r/galera_sst_rsync_data_dir.result index ff85a7d6c0f..d41d0d34e75 100644 --- a/mysql-test/suite/galera/r/galera_sst_rsync_data_dir.result +++ b/mysql-test/suite/galera/r/galera_sst_rsync_data_dir.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 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 07433399081..ce49b491778 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_insert.result b/mysql-test/suite/galera/r/galera_toi_ddl_fk_insert.result index 0dbc89978d4..0ecc4a4619f 100644 --- a/mysql-test/suite/galera/r/galera_toi_ddl_fk_insert.result +++ b/mysql-test/suite/galera/r/galera_toi_ddl_fk_insert.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_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..bbe181ce6f5 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 @@ -34,6 +48,7 @@ COUNT(*) = 0 SELECT COUNT(*) = 1 FROM t2; COUNT(*) = 1 1 +SET debug_sync='RESET'; connection node_2; SELECT COUNT(*) = 0 FROM t1; COUNT(*) = 0 @@ -41,9 +56,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 73285d723c1..081a82e6e7d 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); @@ -11,7 +13,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 77848bc751f..5db1be8c910 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_auto_inc_control_on.result b/mysql-test/suite/galera/r/galera_var_auto_inc_control_on.result index b71cf4c831d..48c649b66a8 100644 --- a/mysql-test/suite/galera/r/galera_var_auto_inc_control_on.result +++ b/mysql-test/suite/galera/r/galera_var_auto_inc_control_on.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, node VARCHAR(10)) ENGINE=InnoDB; SELECT @@auto_increment_increment = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'); 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..8c1070e43ce 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 @@ -11,7 +15,7 @@ Variable_name Value wsrep_ready OFF SHOW STATUS LIKE 'wsrep_cluster_status'; Variable_name Value -wsrep_cluster_status non-Primary +wsrep_cluster_status Disconnected SHOW STATUS LIKE 'wsrep_local_state'; Variable_name Value wsrep_local_state 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 26798e51926..6a2e501eee2 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..33536d95186 100644 --- a/mysql-test/suite/galera/r/galera_var_dirty_reads.result +++ b/mysql-test/suite/galera/r/galera_var_dirty_reads.result @@ -1,6 +1,6 @@ -connection node_1; connection node_2; connection node_1; +connection node_1; connection node_2; connection node_2; CREATE TABLE t1(i INT) ENGINE=INNODB; @@ -16,7 +16,7 @@ Variable_name Value wsrep_ready OFF SHOW STATUS LIKE 'wsrep_cluster_status'; Variable_name Value -wsrep_cluster_status non-Primary +wsrep_cluster_status Disconnected SELECT * FROM t1; ERROR 08S01: WSREP has not yet prepared node for application use SELECT 1 FROM t1; @@ -52,4 +52,3 @@ i DROP TABLE t1; disconnect node_2; disconnect node_1; -# End of test 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..48c845a4c2b --- /dev/null +++ b/mysql-test/suite/galera/r/galera_var_ignore_apply_errors.result @@ -0,0 +1,186 @@ +connection node_2; +connection node_1; +connection node_2; +SET GLOBAL wsrep_ignore_apply_errors = 1; +connection node_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; +connection node_2; +SET GLOBAL wsrep_ignore_apply_errors = 2; +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; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +DROP TABLE t1; +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; +COUNT(*) = 1 +1 +connection node_2; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +connection node_2; +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; +COUNT(*) = 0 +1 +connection node_2; +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; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +connection node_2; +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; +COUNT(*) = 0 +1 +connection node_2; +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; +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; +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; +COUNT(*) = 0 +1 +connection node_2; +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; +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; +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; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM child; +COUNT(*) = 0 +1 +connection node_2; +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; +connection node_2; +SET GLOBAL wsrep_ignore_apply_errors = 4; +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("Can't find record in 't.*'"); +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 7696d1e3f4f..cf45861c8ad 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 caf98566595..b95e5773830 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_retry_autocommit.result b/mysql-test/suite/galera/r/galera_var_retry_autocommit.result index c0bf6035184..b8943464cb7 100644 --- a/mysql-test/suite/galera/r/galera_var_retry_autocommit.result +++ b/mysql-test/suite/galera/r/galera_var_retry_autocommit.result @@ -1,15 +1,17 @@ +connection node_2; +connection node_1; connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; SET SESSION wsrep_retry_autocommit = 0; -SET DEBUG_SYNC = 'wsrep_before_replication SIGNAL before_rep WAIT_FOR continue'; +SET DEBUG_SYNC = 'wsrep_before_certification SIGNAL before_cert WAIT_FOR continue'; INSERT INTO t1 (f1) VALUES (2); connection node_1a; -SET DEBUG_SYNC = 'now WAIT_FOR before_rep'; +SET DEBUG_SYNC = 'now WAIT_FOR before_cert'; connection node_2; TRUNCATE TABLE t1; connection node_1; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction SELECT COUNT(*) = 0 FROM t1; COUNT(*) = 0 1 @@ -18,10 +20,10 @@ DROP TABLE t1; connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; SET SESSION wsrep_retry_autocommit = 1; -SET DEBUG_SYNC = 'wsrep_before_replication SIGNAL before_rep WAIT_FOR continue'; -INSERT INTO t1 (f1) VALUES (2); +SET DEBUG_SYNC = 'wsrep_before_certification SIGNAL before_cert WAIT_FOR continue'; +INSERT INTO t1 (f1) VALUES (3); connection node_1a; -SET DEBUG_SYNC = 'now WAIT_FOR before_rep'; +SET DEBUG_SYNC = 'now WAIT_FOR before_cert'; connection node_2; TRUNCATE TABLE t1; connection node_1; @@ -34,10 +36,10 @@ connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; SET SESSION wsrep_retry_autocommit = 1; SET GLOBAL debug_dbug = '+d,sync.wsrep_retry_autocommit'; -SET DEBUG_SYNC = 'wsrep_before_replication SIGNAL before_rep WAIT_FOR continue EXECUTE 2'; -INSERT INTO t1 VALUES (2);; +SET DEBUG_SYNC = 'wsrep_before_certification SIGNAL before_cert WAIT_FOR continue EXECUTE 2'; +INSERT INTO t1 VALUES (4);; connection node_1a; -SET DEBUG_SYNC = 'now WAIT_FOR before_rep'; +SET DEBUG_SYNC = 'now WAIT_FOR before_cert'; connection node_2; TRUNCATE TABLE t1; connection node_1a; @@ -45,7 +47,7 @@ SET DEBUG_SYNC = 'now WAIT_FOR wsrep_retry_autocommit_reached'; SELECT COUNT(*) = 0 FROM t1; COUNT(*) = 0 1 -SET DEBUG_SYNC = 'now SIGNAL wsrep_retry_autocommit_continue WAIT_FOR before_rep'; +SET DEBUG_SYNC = 'now SIGNAL wsrep_retry_autocommit_continue WAIT_FOR before_cert'; connection node_2; TRUNCATE TABLE t1; connection node_1a; @@ -53,7 +55,7 @@ SELECT COUNT(*) = 0 FROM t1; COUNT(*) = 0 1 connection node_1; -ERROR 40001: Deadlock: wsrep aborted transaction +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction SET DEBUG_SYNC = 'RESET'; SET GLOBAL debug_dbug = NULL; DROP TABLE t1; @@ -61,8 +63,8 @@ connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; SET SESSION wsrep_retry_autocommit = 64; SET GLOBAL debug_dbug = '+d,sync.wsrep_retry_autocommit'; -SET DEBUG_SYNC = 'wsrep_before_replication SIGNAL before_rep WAIT_FOR continue EXECUTE 64'; -INSERT INTO t1 VALUES (2); +SET DEBUG_SYNC = 'wsrep_before_certification SIGNAL before_cert WAIT_FOR continue EXECUTE 64'; +INSERT INTO t1 VALUES (5); connection node_1; SELECT COUNT(*) = 1 FROM t1; COUNT(*) = 1 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 c28cc091ae9..168b45154b8 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,7 @@ +connection node_2; +connection node_1; +connection node_1; +connection node_2; connection node_1; CREATE TABLE t1 (f1 INT PRIMARY KEY) Engine=InnoDB; CREATE TABLE t2 (f1 INT AUTO_INCREMENT PRIMARY KEY) Engine=InnoDB; @@ -13,6 +17,9 @@ 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 COMMAND != 'Daemon'; +COUNT(*) +3 SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; COUNT(*) 1 @@ -20,8 +27,11 @@ SET GLOBAL wsrep_slave_threads = 64; connection node_1; INSERT INTO t1 VALUES (1); connection node_2; -SELECT COUNT(*) = 1 FROM t1; -COUNT(*) = 1 +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; +COUNT(*) 1 SET GLOBAL wsrep_slave_threads = 1; connection node_1; @@ -32,26 +42,42 @@ COUNT(*) 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; +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(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND COMMAND != 'Daemon'; +COUNT(*) +3 connection node_1; -CREATE TABLE t1 (i INT AUTO_INCREMENT PRIMARY KEY) ENGINE=INNODB; +SET GLOBAL wsrep_slave_threads = 1; connection node_2; -SET GLOBAL wsrep_slave_threads = 4; 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 +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +SELECT COUNT(*) FROM t2; +COUNT(*) +192 +connection node_1; +SELECT COUNT(*) FROM t1; +COUNT(*) 1 +SELECT COUNT(*) FROM t2; +COUNT(*) +192 +DROP TABLE t1; +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 41b915fa5bf..bc4113ffb1c 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; CALL mtr.add_suppression("WSREP: Stray state UUID msg:.*"); CALL mtr.add_suppression("WSREP: Sending JOIN failed:.*"); CALL mtr.add_suppression("There are no nodes in the same segment that will ever be able to become donors, yet there is a suitable donor outside"); 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_wsrep_provider_unset_set.result b/mysql-test/suite/galera/r/galera_wsrep_provider_unset_set.result index d56d9340474..7a645407004 100644 --- a/mysql-test/suite/galera/r/galera_wsrep_provider_unset_set.result +++ b/mysql-test/suite/galera/r/galera_wsrep_provider_unset_set.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_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 bbcbb06a685..56f56d3b023 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#216.result b/mysql-test/suite/galera/r/mysql-wsrep#216.result new file mode 100644 index 00000000000..b07589d0c04 --- /dev/null +++ b/mysql-test/suite/galera/r/mysql-wsrep#216.result @@ -0,0 +1,11 @@ +SET GLOBAL wsrep_debug = ON; +CREATE USER u1 IDENTIFIED BY 'plaintext_password'; +CREATE USER u1 IDENTIFIED BY 'plaintext_password'; +ERROR HY000: Operation CREATE USER failed for 'u1'@'%' +0 +0 +2 +1 +DROP USER u1; +CALL mtr.add_suppression('Operation CREATE USER failed'); +
\ No newline at end of file diff --git a/mysql-test/suite/galera/r/mysql-wsrep#237.result b/mysql-test/suite/galera/r/mysql-wsrep#237.result index 19503dd5781..bc348613d25 100644 --- a/mysql-test/suite/galera/r/mysql-wsrep#237.result +++ b/mysql-test/suite/galera/r/mysql-wsrep#237.result @@ -1,6 +1,8 @@ +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'; +SET DEBUG_SYNC = 'wsrep_before_certification WAIT_FOR continue'; INSERT INTO t values (1);; connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; connection node_1a; 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#33.result b/mysql-test/suite/galera/r/mysql-wsrep#33.result index 6a5251204b9..5589faad8b1 100644 --- a/mysql-test/suite/galera/r/mysql-wsrep#33.result +++ b/mysql-test/suite/galera/r/mysql-wsrep#33.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; connection node_2; Setting SST method to mysqldump ... @@ -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'); @@ -114,5 +119,6 @@ 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"); connection node_2; Restarting server ... diff --git a/mysql-test/suite/galera/r/mysql-wsrep#332.result b/mysql-test/suite/galera/r/mysql-wsrep#332.result index 8667f5e9c41..565979a93ae 100644 --- a/mysql-test/suite/galera/r/mysql-wsrep#332.result +++ b/mysql-test/suite/galera/r/mysql-wsrep#332.result @@ -1,26 +1,38 @@ +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; CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER) ENGINE=INNODB; INSERT INTO p VALUES (1, 0); INSERT INTO p VALUES (2, 0); INSERT INTO c VALUES (1, 1); INSERT INTO c VALUES (2, 2); +connection node_1; SET AUTOCOMMIT=ON; START TRANSACTION; UPDATE p SET f1 = f1 + 100; +connection node_1a; SET SESSION wsrep_sync_wait = 0; SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; ALTER TABLE c ADD FOREIGN KEY (p_id) REFERENCES p(f1); +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 @@ -31,6 +43,7 @@ f1 p_id 2 2 DROP TABLE c; 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, p_id1 INTEGER, p_id2 INTEGER) ENGINE=INNODB; @@ -38,23 +51,31 @@ INSERT INTO p1 VALUES (1, 0), (2, 0); INSERT INTO p2 VALUES (1, 0), (2, 0); INSERT INTO c VALUES (1, 1, 1); INSERT INTO c VALUES (2, 2, 2); +connection node_1; SET AUTOCOMMIT=ON; START TRANSACTION; UPDATE p1 SET f1 = f1 + 100; +connection node_1a; SET SESSION wsrep_sync_wait = 0; SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; ALTER TABLE c ADD FOREIGN KEY (p_id1) REFERENCES p1(f1), ADD FOREIGN KEY (p_id2) REFERENCES p2(f1); +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 p1; f1 f2 1 0 @@ -70,6 +91,7 @@ f1 p_id1 p_id2 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, p_id1 INTEGER, p_id2 INTEGER) ENGINE=INNODB; @@ -77,23 +99,31 @@ INSERT INTO p1 VALUES (1, 0), (2, 0); INSERT INTO p2 VALUES (1, 0), (2, 0); INSERT INTO c VALUES (1, 1, 1); INSERT INTO c VALUES (2, 2, 2); +connection node_1; SET AUTOCOMMIT=ON; START TRANSACTION; UPDATE p2 SET f1 = f1 + 100; +connection node_1a; SET SESSION wsrep_sync_wait = 0; SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; ALTER TABLE c ADD FOREIGN KEY (p_id1) REFERENCES p1(f1), ADD FOREIGN KEY (p_id2) REFERENCES p2(f1); +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 p1; f1 f2 1 0 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 bdf6df25589..e34028ab04f 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(*) FROM t1; COUNT(*) 20002 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(*) FROM t1; COUNT(*) 20002 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 8592a68141c..5dabd38a982 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/versioning_trx_id.result b/mysql-test/suite/galera/r/versioning_trx_id.result index f15916e51a5..232cca202c0 100644 --- a/mysql-test/suite/galera/r/versioning_trx_id.result +++ b/mysql-test/suite/galera/r/versioning_trx_id.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 (a int, s bigint unsigned as row start, e bigint unsigned as row end, period for system_time(s,e)) engine=InnoDB with system versioning; 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_sr.result b/mysql-test/suite/galera/r/wsrep_trx_fragment_size_sr.result new file mode 100644 index 00000000000..4139ecd6472 --- /dev/null +++ b/mysql-test/suite/galera/r/wsrep_trx_fragment_size_sr.result @@ -0,0 +1,15 @@ +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; +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/suite.pm b/mysql-test/suite/galera/suite.pm index 1aabc697db1..a9fd1568f9c 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -9,9 +9,9 @@ return "Not run for embedded server" if $::opt_embedded_server; return "WSREP is not compiled in" unless defined $::mysqld_variables{'wsrep-on'}; my ($provider) = grep { -f $_ } $ENV{WSREP_PROVIDER}, - "/usr/lib64/galera-3/libgalera_smm.so", + "/usr/lib64/galera-4/libgalera_smm.so", "/usr/lib64/galera/libgalera_smm.so", - "/usr/lib/galera-3/libgalera_smm.so", + "/usr/lib/galera-4/libgalera_smm.so", "/usr/lib/galera/libgalera_smm.so"; return "No wsrep provider library" unless -f $provider; @@ -81,6 +81,8 @@ push @::global_suppressions, qr|WSREP: .*core_handle_uuid_msg.*|, qr(WSREP: --wsrep-causal-reads=ON takes precedence over --wsrep-sync-wait=0. WSREP_SYNC_WAIT_BEFORE_READ is on), qr|WSREP: JOIN message from member .* in non-primary configuration. Ignored.|, + qr|Query apply failed:*|, + qr(WSREP: Ignoring error*), qr(WSREP: Failed to remove page file .*), qr(WSREP: wsrep_sst_method is set to 'mysqldump' yet mysqld bind_address is set to .*), ); 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..637d656996e --- /dev/null +++ b/mysql-test/suite/galera/t/GCF-939.test @@ -0,0 +1,31 @@ +# +# 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 +# TODO replace_regex is somehow broken, it will filter out +# result totally if replacement string is already in result +# fixed this temporarily by calling list_files twice +# to get GRA_.log two times, this works for some reason +# +--replace_regex /GRA_.+\.log/GRA_.log/ +--list_files $MYSQLTEST_VARDIR/mysqld.2/data GRA_*.log +--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..b52db4c68b0 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=ON; 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-286.test b/mysql-test/suite/galera/t/MW-286.test index 426b4493bb7..9c849861001 100644 --- a/mysql-test/suite/galera/t/MW-286.test +++ b/mysql-test/suite/galera/t/MW-286.test @@ -4,31 +4,55 @@ --source include/galera_cluster.inc --source include/have_innodb.inc ---source include/big_test.inc - +--source include/have_debug_sync.inc + --connection node_1 -CREATE TABLE ten (f1 INTEGER) Engine=InnoDB; -INSERT INTO ten VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; - # Insert some values before the ALTER -INSERT INTO t1 (f1) SELECT 000000 + (10000 * a1.f1) + (1000 * a2.f1) + (100 * a3.f1) + (10 * a4.f1) + a5.f1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5; - -# Insert more values while the ALTER is running ---send INSERT INTO t1 (f1) SELECT 100000 + (10000 * a1.f1) + (1000 * a2.f1) + (100 * a3.f1) + (10 * a4.f1) + a5.f1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5; +INSERT INTO t1 (f1) VALUES (1), (2), (3); +# +# run ALTER with no wsrep replication +# --connection node_2 SET GLOBAL wsrep_desync = TRUE; SET wsrep_on = FALSE; ---error 0,ER_QUERY_INTERRUPTED -ALTER TABLE t1 ADD PRIMARY KEY (f1); +# +# stop ALTER processing after it has acquired exclusive MDL lock +# +SET SESSION debug_sync = "alter_table_inplace_after_lock_upgrade SIGNAL mdl_locked WAIT_FOR mdl_continue"; + +--send ALTER TABLE t1 ADD PRIMARY KEY (f1); + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a +SET SESSION debug_sync = "now WAIT_FOR mdl_locked"; + +# +# replicate conflicting insert from node_1 +# +--connection node_1 +INSERT INTO t1(f1) VALUES (11); + +# +# let parked ALTER processing to continue after the conflict +# +--connection node_2a +SET debug_sync = "now SIGNAL mdl_continue"; +SET debug_sync='RESET'; + +# +# ALTER should have been aborted with query interupted error code +# +--connection node_2 +--error ER_QUERY_INTERRUPTED +--reap SET wsrep_on = TRUE; SET GLOBAL wsrep_desync = FALSE; --connection node_1 -reap; + DROP TABLE t1; -DROP TABLE ten; 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 09aad1bcf60..097d4ac4ff6 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/big_test.inc @@ -25,7 +30,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 @@ -44,14 +49,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 4bdbfb2ecff..67715c24992 100644 --- a/mysql-test/suite/galera/t/MW-336.test +++ b/mysql-test/suite/galera/t/MW-336.test @@ -11,9 +11,8 @@ CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; SET GLOBAL wsrep_slave_threads = 10; SET GLOBAL wsrep_slave_threads = 1; - --let $wait_timeout=600 ---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 SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND (STATE IS NULL OR STATE NOT LIKE 'InnoDB%'); @@ -31,11 +30,11 @@ while ($count) --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; @@ -62,7 +61,7 @@ while ($count) } --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..c8f8c974019 100644 --- a/mysql-test/suite/galera/t/MW-369.test +++ b/mysql-test/suite/galera/t/MW-369.test @@ -24,7 +24,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 CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, @@ -244,3 +244,101 @@ SELECT * FROM c; DROP TABLE c; DROP TABLE p; +--echo # +--echo # Start of 10.4 tests +--echo # +# +# Test F Outline: +# =============== +# +# Test two concurrent INSERTs on the child table. +# +# The pf table will originally have row (1) +# The cf table will originally be empty +# +# A new row (10, 1) pointing to parent row (1) is inserted from +# connection node_2. A transaction which tries to INSERT another child +# row (20, 1), pointing to the same parent, is run from connection node_1. +# +# Expected Outcome: +# ================= +# Both INSERTs should succeed since they don't modify the common parent +# key. +# +# At the end of the test: +# parent table should have row (1) +# child table should have rows (10, 1), (20, 1) + +--connection node_1 + +CREATE TABLE pf (f1 INTEGER PRIMARY KEY) ENGINE=INNODB; +CREATE TABLE cf ( + f1 INTEGER PRIMARY KEY, + p_id INTEGER, + CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES pf (f1) +); + +INSERT INTO pf VALUES (1); + +# This is run on node1: +--let $mw_369_parent_query = INSERT INTO cf (f1, p_id) VALUES (10, 1) +# This is run on node2: +--let $mw_369_child_query = INSERT INTO cf (f1, p_id) VALUES (20, 1) +--source MW-369.inc + +--connection node_1 +--reap + +--connection node_2 +SELECT * FROM pf; +SELECT * FROM cf; + +DROP TABLE cf; +DROP TABLE pf; + +# +# Test G Outline: +# =============== +# +# This test is similar to test B where a existing +# child table row is updated concurrently from another node +# with a transaction which updates the parent table, except +# that here the child table row is inserted, not updated. +# +# The pg table will originally have rows (1, 0), (2, 0). +# The cg table will originally be empty +# +# Expected outcome: +# ================ +# +# Both UPDATE and INSERT should succeed since they are done to separate tables +# and UPDATE to parent row does not touch the foreign key referenced by the +# child row INSERT. The parent table shall contain rows (1, 1), (2, 0). +# The child table shall contain row (1, 1, 0) which points to parent table +# row (1, 0). +# + +--connection node_1 +CREATE TABLE pg (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB; +CREATE TABLE cg (f1 INTEGER PRIMARY KEY, p_id INTEGER, + f2 INTEGER, + CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES pg (f1)) ; + +INSERT INTO pg VALUES (1, 0); +INSERT INTO pg VALUES (2, 0); + +--let mw_369_parent_query = UPDATE pg SET f2 = 1 WHERE f1 = 1 +--let $mw_369_child_query = INSERT INTO cg VALUES (1, 1, 0) +--source MW-369.inc + +# Commit succeeds +--connection node_1 +--reap + +--connection node_2 +SELECT * FROM pg; +SELECT * FROM cg; + +DROP TABLE cg; +DROP TABLE pg; + diff --git a/mysql-test/suite/galera/t/MW-388.test b/mysql-test/suite/galera/t/MW-388.test index de1ac52bf3e..9cf176434ba 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; @@ -41,11 +40,11 @@ SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; --connection node_1 SET SESSION wsrep_sync_wait = 0; -SET SESSION DEBUG_SYNC = 'wsrep_after_replication SIGNAL wsrep_after_replication_reached WAIT_FOR wsrep_after_replication_continue'; +SET SESSION DEBUG_SYNC = 'wsrep_after_certification SIGNAL wsrep_after_certification_reached WAIT_FOR wsrep_after_certification_continue'; --send CALL insert_proc (); --connection node_1a -SET SESSION DEBUG_SYNC = "now WAIT_FOR wsrep_after_replication_reached"; +SET SESSION DEBUG_SYNC = "now WAIT_FOR wsrep_after_certification_reached"; SET GLOBAL DEBUG_DBUG = ""; 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..48eada95cb8 100644 --- a/mysql-test/suite/galera/t/MW-416.test +++ b/mysql-test/suite/galera/t/MW-416.test @@ -2,11 +2,10 @@ --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 @@ -131,4 +130,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-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/galera#500.test b/mysql-test/suite/galera/t/galera#500.test index 3c8490b6907..60f303b7103 100644 --- a/mysql-test/suite/galera/t/galera#500.test +++ b/mysql-test/suite/galera/t/galera#500.test @@ -8,6 +8,10 @@ --source include/galera_cluster.inc --source include/galera_have_debug_sync.inc +--let $node_1=node_1 +--let $node_2=node_2 +--source suite/galera/include/auto_increment_offset_save.inc + # Force node_2 gcomm background thread to terminate via exception. --connection node_2 --let $wsrep_cluster_address = `SELECT @@wsrep_cluster_address` @@ -36,3 +40,5 @@ 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."); + +--source suite/galera/include/auto_increment_offset_restore.inc 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.cnf b/mysql-test/suite/galera/t/galera_as_master_gtid.cnf index 19517556331..75caba5420a 100644 --- a/mysql-test/suite/galera/t/galera_as_master_gtid.cnf +++ b/mysql-test/suite/galera/t/galera_as_master_gtid.cnf @@ -1,8 +1,6 @@ !include ../galera_2nodes_as_master.cnf [mysqld] -gtid-mode=ON log-bin=mysqld-bin log-slave-updates -enforce-gtid-consistency binlog-format=ROW 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.cnf b/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.cnf index 19517556331..75caba5420a 100644 --- a/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.cnf +++ b/mysql-test/suite/galera/t/galera_as_master_gtid_change_master.cnf @@ -1,8 +1,6 @@ !include ../galera_2nodes_as_master.cnf [mysqld] -gtid-mode=ON log-bin=mysqld-bin log-slave-updates -enforce-gtid-consistency binlog-format=ROW 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..da92437b118 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,5 @@ DROP TABLE t1; STOP SLAVE; RESET SLAVE ALL; ---connection node_1 +--connection node_3 RESET MASTER; 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..e0c8bf29682 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,5 @@ DROP TABLE t1; STOP SLAVE; RESET SLAVE ALL; ---connection node_1 +--connection node_3 RESET MASTER; 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..81b6d446ba6 --- /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/galera_cluster.inc +--source include/have_log_bin.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_1 +SET global wsrep_on=OFF; +RESET MASTER; +SET global wsrep_on=ON; + +--connection node_3 +RESET MASTER; + +--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_3, MASTER_USER='root'; +--enable_query_log +START SLAVE; + +--connection node_3 +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_1 + +--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 = 1 2 +--source include/diff_servers.inc + +--connection node_1 +--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_3 +DROP SCHEMA test1; +DROP SCHEMA test2; + +--sleep 1 + +--connection node_1 +--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..31c0b9ca162 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,5 @@ 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 RESET MASTER; 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_mariabackup.cnf b/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.cnf index bd6bf9d4f98..cddb8e0e174 100644 --- a/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.cnf +++ b/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.cnf @@ -5,7 +5,7 @@ wsrep_sst_method=mariabackup wsrep_sst_auth="root:" [mysqld.1] -wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true' +wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=10M;pc.ignore_sb=true' [mysqld.2] -wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=1;pc.ignore_sb=true' +wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=10M;pc.ignore_sb=true' diff --git a/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.test b/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.test index 9d5f821a170..ed3674ad0e0 100644 --- a/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.test +++ b/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.test @@ -45,6 +45,8 @@ DELIMITER ;| --connection node_2a --source include/kill_galera.inc +--remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat + --sleep 10 --source include/start_mysqld.inc --sleep 25 @@ -59,7 +61,6 @@ INSERT INTO t1 VALUES (DEFAULT); --disable_query_log --eval KILL CONNECTION $connection_id --enable_query_log - INSERT INTO t1 VALUES (DEFAULT); --connection node_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..a828701cd0e --- /dev/null +++ b/mysql-test/suite/galera/t/galera_bf_abort_group_commit.test @@ -0,0 +1,77 @@ +# +# 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 +--source include/galera_have_debug_sync.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_sr/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_sr/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_sr/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_sr/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_sr/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_sr/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_sr/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_sr/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_sr/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_sr/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_sr/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..c7af8375b3f --- /dev/null +++ b/mysql-test/suite/galera/t/galera_bf_abort_shutdown.test @@ -0,0 +1,33 @@ +# +# 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 +--source include/have_debug_sync.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_1 +CREATE TABLE t1 (f1 INT PRIMARY KEY); + +--connection node_2 +SET DEBUG_SYNC = 'wsrep_before_certification 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 + +# Restore original auto_increment_offset values. +--let $node_2=node_2a +--source include/auto_increment_offset_restore.inc + +--connection node_1 + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_commit_empty.test b/mysql-test/suite/galera/t/galera_commit_empty.test new file mode 100644 index 00000000000..4e1a1e4eb2c --- /dev/null +++ b/mysql-test/suite/galera/t/galera_commit_empty.test @@ -0,0 +1,35 @@ +# Test empty transactions. +# +# Check that the empty transaction gets terminated by starting and new +# transaction after it. If the empty transaction is not terminated +# appropriately, the following START TRANSACTION will fail. +# +# Also check that empty transactions don't generate any write sets. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` + +START TRANSACTION; +COMMIT; + +START TRANSACTION; +COMMIT; + +START TRANSACTION READ ONLY; +COMMIT; + +START TRANSACTION; +COMMIT; + +START TRANSACTION; +START TRANSACTION; +COMMIT; + +--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 AS wsrep_last_committed_diff +--enable_query_log 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 3d4a7da7b54..3f8be268135 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(*) `expect 48` FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep_%'; SELECT VARIABLE_NAME, VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES 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..ee64e147f65 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; @@ -55,7 +55,7 @@ SET SESSION innodb_lock_wait_timeout=1; SET SESSION wait_timeout=1; --error ER_LOCK_WAIT_TIMEOUT -INSERT INTO t2 VALUES (2); +INSERT INTO t1 VALUES (2); --connection node_2a UNLOCK TABLES; 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..d728a094f10 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 @@ -13,6 +13,14 @@ SET SESSION wsrep_sync_wait = 0; --source include/kill_galera.inc --connection node_1 + +# +# Wait until the configuration change is over in order to avoid +# replication error due to configuration change. +# +--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 (f2) VALUES (REPEAT('x', 1024 * 1024 * 10)); INSERT INTO t1 (f2) VALUES (REPEAT('x', 1024 * 1024 * 10)); INSERT INTO t1 (f2) VALUES (REPEAT('x', 1024 * 1024 * 10)); @@ -48,8 +56,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_gcs_fragment.test b/mysql-test/suite/galera/t/galera_gcs_fragment.test index 80d3a5cb659..d2593fec8c8 100644 --- a/mysql-test/suite/galera/t/galera_gcs_fragment.test +++ b/mysql-test/suite/galera/t/galera_gcs_fragment.test @@ -1,7 +1,7 @@ # Test fragmentation over configuration changes --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 # Save original auto_increment_offset values. --let $node_1=node_1 @@ -54,7 +54,7 @@ INSERT INTO t1 VALUES (2, "bbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa # Deadlock error should be returned since write set send was # interrupted by gcs --connection node_1 ---error ER_LOCK_DEADLOCK +--error ER_ERROR_DURING_COMMIT --reap # Do additional insert to verify that node_1 remain operational 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..df55ea03cb0 100644 --- a/mysql-test/suite/galera/t/galera_gtid_slave.test +++ b/mysql-test/suite/galera/t/galera_gtid_slave.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; CREATE TABLE t2 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES(1); @@ -49,31 +50,43 @@ INSERT INTO t1 VALUES(2); INSERT INTO t1 VALUES(3); SELECT @@global.gtid_binlog_state; ---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_1 --let $wait_condition = SELECT COUNT(*) = 3 FROM t1; --source include/wait_condition.inc INSERT INTO t1 VALUES(4); SELECT @@global.gtid_binlog_state; ---connection node_1 +--connection node_3 DROP TABLE t1,t2; +# +# 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'; --source include/wait_condition.inc ---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 --connection node_2 STOP SLAVE; RESET SLAVE ALL; +SET GLOBAL wsrep_on=OFF; reset master; +SET GLOBAL wsrep_on=ON; ---connection node_3 +--connection node_1 +SET GLOBAL wsrep_on=OFF; reset master; +SET GLOBAL wsrep_on=ON; ---connection node_1 +--connection node_3 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 3ed7ec1d09e..d03445d537a 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,30 +169,31 @@ 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; +set global wsrep_on=ON; + --disable_warnings set global gtid_slave_pos=""; --enable_warnings -reset master; - ---echo #Connection 3 ---connection node_3 -reset master; --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_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..42f210170bc 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 @@ -43,8 +43,6 @@ UPDATE t1 SET f2 = 'c' WHERE f1 > 2; # ... and restart provider to force IST --echo Loading wsrep_provider ... --disable_query_log -# base_port setting is lost for some reason when unloading provider, so we need to restore it ---eval SET GLOBAL wsrep_provider_options= 'base_port=$NODE_GALERAPORT_2'; --eval SET GLOBAL wsrep_provider = '$wsrep_provider_orig'; # Make sure IST will block ... --let $galera_sync_point = recv_IST_after_apply_trx diff --git a/mysql-test/suite/galera/t/galera_kill_applier.test b/mysql-test/suite/galera/t/galera_kill_applier.test index d04b72bce0a..b66e0bcbbd0 100644 --- a/mysql-test/suite/galera/t/galera_kill_applier.test +++ b/mysql-test/suite/galera/t/galera_kill_applier.test @@ -6,7 +6,6 @@ --source include/have_innodb.inc --connection node_1 ---sleep 2 --let $applier_thread = `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE IS NULL LIMIT 1` --disable_query_log 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_many_rows.cnf b/mysql-test/suite/galera/t/galera_many_rows.cnf new file mode 100644 index 00000000000..24c4cc1c60d --- /dev/null +++ b/mysql-test/suite/galera/t/galera_many_rows.cnf @@ -0,0 +1,10 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +innodb-status-output=ON +innodb-status-output-locks=ON + +[mysqld.2] +innodb-status-output=ON +innodb-status-output-locks=ON + diff --git a/mysql-test/suite/galera/t/galera_many_rows.test b/mysql-test/suite/galera/t/galera_many_rows.test index 58ba85e1b9e..67e2eb6edbf 100644 --- a/mysql-test/suite/galera/t/galera_many_rows.test +++ b/mysql-test/suite/galera/t/galera_many_rows.test @@ -3,6 +3,11 @@ --source include/galera_cluster.inc --source include/have_innodb.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_1 SET SESSION innodb_lock_wait_timeout=600; SET SESSION lock_wait_timeout=600; @@ -52,3 +57,5 @@ COMMIT; DROP TABLE t1; DROP TABLE ten; + +--source include/auto_increment_offset_restore.inc 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..5a33c16c86e 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; @@ -44,7 +44,7 @@ UNLOCK TABLES; --eval SET SESSION wsrep_sync_wait = $wsrep_sync_wait_orig; SELECT COUNT(*) = 1 FROM t1; SELECT COUNT(*) = 1 FROM t2; -SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'committed%'; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%committed%'; --eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig; DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test b/mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test index 644b4687cb3..203d18b85a6 100644 --- a/mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test +++ b/mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test @@ -12,13 +12,16 @@ --source include/galera_connect.inc --connection node_1 -CREATE TABLE ten (f1 INTEGER); +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; + --connection node_2 --let $wsrep_slave_threads_orig = `SELECT @@wsrep_slave_threads` SET GLOBAL wsrep_slave_threads = 4; +--let $wait_condition = SELECT VARIABLE_VALUE = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_thread_count'; +--source include/wait_condition.inc --connection node_1 --send INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; @@ -31,16 +34,18 @@ SET GLOBAL wsrep_slave_threads = 4; --connection node_1 --reap +SELECT COUNT(*) FROM t1; +SELECT COUNT(DISTINCT f1) FROM t1; --connection node_1a --reap +SELECT COUNT(*) FROM t1; +SELECT COUNT(DISTINCT f1) FROM t1; --connection node_2 --reap SELECT COUNT(*) FROM t1; SELECT COUNT(DISTINCT f1) FROM t1; -SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE - USER = 'system user' AND STATE NOT LIKE 'InnoDB%'; --disable_query_log --eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig; diff --git a/mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test b/mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test index 8680d62a36d..d2156cb3577 100644 --- a/mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test +++ b/mysql-test/suite/galera/t/galera_parallel_autoinc_manytrx.test @@ -42,7 +42,7 @@ while ($count) SELECT COUNT(*) = 20000 FROM t1; SELECT COUNT(DISTINCT f1) = 20000 FROM t1; -SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'committed%'; +SELECT COUNT(*) = 4 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'wsrep applier committed%'; --disable_query_log --eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig; 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..1621414aff5 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_pc_recovery.test @@ -0,0 +1,102 @@ +# +# 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 + +# Save galera ports +--connection node_1 +--source suite/galera/include/galera_base_port.inc +--let $NODE_GALERAPORT_1 = $_NODE_GALERAPORT + +--connection node_2 +--source suite/galera/include/galera_base_port.inc +--let $NODE_GALERAPORT_2 = $_NODE_GALERAPORT + +--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.cnf b/mysql-test/suite/galera/t/galera_sst_mysqldump.cnf index 574ae28b54a..0d05038f2fb 100644 --- a/mysql-test/suite/galera/t/galera_sst_mysqldump.cnf +++ b/mysql-test/suite/galera/t/galera_sst_mysqldump.cnf @@ -5,7 +5,7 @@ [mysqld.1] wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true' - +wsrep_sync_wait=0 [mysqld.2] wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=1;pc.ignore_sb=true' - +wsrep_sync_wait=0 diff --git a/mysql-test/suite/galera/t/galera_sst_mysqldump.test b/mysql-test/suite/galera/t/galera_sst_mysqldump.test index 835fac94a68..cce4d374a6d 100644 --- a/mysql-test/suite/galera/t/galera_sst_mysqldump.test +++ b/mysql-test/suite/galera/t/galera_sst_mysqldump.test @@ -1,6 +1,5 @@ --source include/big_test.inc --source include/galera_cluster.inc - --source suite/galera/include/galera_sst_set_mysqldump.inc --let $node_1=node_1 @@ -14,7 +13,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_mysqldump_with_key.cnf b/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.cnf index 44e5573b3e6..b7bca487fc5 100644 --- a/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.cnf +++ b/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.cnf @@ -5,9 +5,13 @@ [mysqld.1] wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true' +wsrep_causal_reads=0 +wsrep_sync_wait=0 [mysqld.2] wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=1;pc.ignore_sb=true' +wsrep_causal_reads=0 +wsrep_sync_wait=0 [mysqld] 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..22a45316306 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; + --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,45 +43,56 @@ 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; +SET debug_sync='RESET'; --connection node_2 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..85ae73ffda4 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; @@ -29,7 +29,7 @@ SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS; # Must return 'OFF' SHOW STATUS LIKE 'wsrep_ready'; -# Must return 'Non-primary' +# Must return 'Disconnected' SHOW STATUS LIKE 'wsrep_cluster_status'; # Must return 0 = 'Initialized' @@ -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..859642a6fdf 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` @@ -32,7 +27,7 @@ SET SESSION wsrep_sync_wait=0; # Must return 'OFF' SHOW STATUS LIKE 'wsrep_ready'; -# Must return 'Non-primary' +# Must return 'Disconnected' SHOW STATUS LIKE 'wsrep_cluster_status'; --error ER_UNKNOWN_COM_ERROR @@ -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,7 @@ SELECT * FROM t1; # Cleanup DROP TABLE t1; +# Restore original auto_increment_offset values. --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..ddf561c8784 --- /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("Can't find record in 't.*'"); +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_retry_autocommit.test b/mysql-test/suite/galera/t/galera_var_retry_autocommit.test index 142f02546b4..df541b774a4 100644 --- a/mysql-test/suite/galera/t/galera_var_retry_autocommit.test +++ b/mysql-test/suite/galera/t/galera_var_retry_autocommit.test @@ -16,11 +16,11 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; SET SESSION wsrep_retry_autocommit = 0; -SET DEBUG_SYNC = 'wsrep_before_replication SIGNAL before_rep WAIT_FOR continue'; +SET DEBUG_SYNC = 'wsrep_before_certification SIGNAL before_cert WAIT_FOR continue'; --send INSERT INTO t1 (f1) VALUES (2) --connection node_1a -SET DEBUG_SYNC = 'now WAIT_FOR before_rep'; +SET DEBUG_SYNC = 'now WAIT_FOR before_cert'; --connection node_2 TRUNCATE TABLE t1; @@ -42,11 +42,11 @@ DROP TABLE t1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; SET SESSION wsrep_retry_autocommit = 1; -SET DEBUG_SYNC = 'wsrep_before_replication SIGNAL before_rep WAIT_FOR continue'; ---send INSERT INTO t1 (f1) VALUES (2) +SET DEBUG_SYNC = 'wsrep_before_certification SIGNAL before_cert WAIT_FOR continue'; +--send INSERT INTO t1 (f1) VALUES (3) --connection node_1a -SET DEBUG_SYNC = 'now WAIT_FOR before_rep'; +SET DEBUG_SYNC = 'now WAIT_FOR before_cert'; --connection node_2 TRUNCATE TABLE t1; @@ -68,12 +68,12 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; SET SESSION wsrep_retry_autocommit = 1; SET GLOBAL debug_dbug = '+d,sync.wsrep_retry_autocommit'; -SET DEBUG_SYNC = 'wsrep_before_replication SIGNAL before_rep WAIT_FOR continue EXECUTE 2'; +SET DEBUG_SYNC = 'wsrep_before_certification SIGNAL before_cert WAIT_FOR continue EXECUTE 2'; ---send INSERT INTO t1 VALUES (2); +--send INSERT INTO t1 VALUES (4); --connection node_1a -SET DEBUG_SYNC = 'now WAIT_FOR before_rep'; +SET DEBUG_SYNC = 'now WAIT_FOR before_cert'; --connection node_2 TRUNCATE TABLE t1; @@ -81,7 +81,7 @@ TRUNCATE TABLE t1; --connection node_1a SET DEBUG_SYNC = 'now WAIT_FOR wsrep_retry_autocommit_reached'; SELECT COUNT(*) = 0 FROM t1; -SET DEBUG_SYNC = 'now SIGNAL wsrep_retry_autocommit_continue WAIT_FOR before_rep'; +SET DEBUG_SYNC = 'now SIGNAL wsrep_retry_autocommit_continue WAIT_FOR before_cert'; --connection node_2 TRUNCATE TABLE t1; @@ -107,9 +107,9 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; SET SESSION wsrep_retry_autocommit = 64; SET GLOBAL debug_dbug = '+d,sync.wsrep_retry_autocommit'; -SET DEBUG_SYNC = 'wsrep_before_replication SIGNAL before_rep WAIT_FOR continue EXECUTE 64'; +SET DEBUG_SYNC = 'wsrep_before_certification SIGNAL before_cert WAIT_FOR continue EXECUTE 64'; ---send INSERT INTO t1 VALUES (2) +--send INSERT INTO t1 VALUES (5) --disable_query_log --disable_result_log @@ -117,7 +117,7 @@ SET DEBUG_SYNC = 'wsrep_before_replication SIGNAL before_rep WAIT_FOR continue E while ($count) { --connection node_1a - SET DEBUG_SYNC = 'now WAIT_FOR before_rep'; + SET DEBUG_SYNC = 'now WAIT_FOR before_cert'; --connection node_2 TRUNCATE TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_var_slave_threads.cnf b/mysql-test/suite/galera/t/galera_var_slave_threads.cnf new file mode 100644 index 00000000000..889c81b4a0a --- /dev/null +++ b/mysql-test/suite/galera/t/galera_var_slave_threads.cnf @@ -0,0 +1,7 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +auto_increment_offset=1 + +[mysqld.2] +auto_increment_offset=2 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 80edcb2aff9..12d8006db4b 100644 --- a/mysql-test/suite/galera/t/galera_var_slave_threads.test +++ b/mysql-test/suite/galera/t/galera_var_slave_threads.test @@ -8,6 +8,11 @@ --source include/have_innodb.inc --let $wsrep_slave_threads_orig = `SELECT @@wsrep_slave_threads` +# 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_1 CREATE TABLE t1 (f1 INT PRIMARY KEY) Engine=InnoDB; CREATE TABLE t2 (f1 INT AUTO_INCREMENT PRIMARY KEY) Engine=InnoDB; @@ -21,6 +26,7 @@ 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 COMMAND != 'Daemon'; SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; # @@ -33,13 +39,15 @@ SET GLOBAL wsrep_slave_threads = 64; INSERT INTO t1 VALUES (1); --connection node_2 ---let $wait_timeout=600 ---let $wait_condition = SELECT COUNT(*) = 1 FROM t1; ---source include/wait_condition.inc +SELECT COUNT(*) FROM t1; -SELECT COUNT(*) = 1 FROM t1; +# +# note, in wsrep API #26, we have 2 rollbacker threads, counted as system user's +# ---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(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; + +--let $wait_condition = SELECT VARIABLE_VALUE = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_thread_count'; --source include/wait_condition.inc # @@ -65,49 +73,122 @@ while ($count) --connection node_2 SELECT COUNT(*) FROM t2; ---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 SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; +--let $wait_condition = SELECT VARIABLE_VALUE = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_thread_count'; +--source include/wait_condition.inc ---eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig +--let $wsrep_cluster_address_node2 = `SELECT @@wsrep_cluster_address` +--let $wsrep_provider_node2 = `SELECT @@wsrep_provider` -DROP TABLE t1; -DROP TABLE t2; +SET GLOBAL wsrep_slave_threads = 5; ---echo # ---echo # lp:1372840 - Changing wsrep_slave_threads causes future connections to hang ---echo # +--let $wait_condition = SELECT VARIABLE_VALUE = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_thread_count'; +--source include/wait_condition.inc ---connection node_1 -CREATE TABLE t1 (i INT AUTO_INCREMENT PRIMARY KEY) ENGINE=INNODB; +SET GLOBAL wsrep_slave_threads = 1; +# +# test phase for bug https://github.com/codership/mysql-wsrep/issues/319 +# + +# shutdown node 2 --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%') +--echo Shutting down server ... +--source include/shutdown_mysqld.inc + +# wait until node_1 is ready as one node cluster +--connection node_1 + +--let $wait_condition = SELECT VARIABLE_VALUE = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_thread_count'; --source include/wait_condition.inc +show status like 'wsrep_cluster_size'; +# 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 VARIABLE_VALUE = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_thread_count'; +--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 VARIABLE_VALUE = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_thread_count'; --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(*) 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 + + +--disable_result_log +--disable_query_log +# 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 +} +--enable_query_log +--enable_result_log + +--connection node_1 +--disable_result_log +--disable_query_log +# 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 +} +--enable_query_log +--enable_result_log + +--let $wait_condition = SELECT VARIABLE_VALUE = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_thread_count'; --source include/wait_condition.inc -SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; + + +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_thread_count'; +--source include/wait_condition.inc + +SELECT COUNT(*) FROM t1; +SELECT COUNT(*) FROM t2; + +--connection node_1 + +SELECT COUNT(*) FROM t1; +SELECT COUNT(*) FROM t2; + +DROP TABLE t1; +DROP TABLE t2; + +# Restore original auto_increment_offset values. +--source include/auto_increment_offset_restore.inc --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/mysql-wsrep#237.test b/mysql-test/suite/galera/t/mysql-wsrep#237.test index cba8dfeb275..174266bdbc5 100644 --- a/mysql-test/suite/galera/t/mysql-wsrep#237.test +++ b/mysql-test/suite/galera/t/mysql-wsrep#237.test @@ -7,13 +7,13 @@ CREATE TABLE t (f1 INTEGER PRIMARY KEY) Engine=InnoDB; --connection node_1 -SET DEBUG_SYNC = 'wsrep_before_replication WAIT_FOR continue'; +SET DEBUG_SYNC = 'wsrep_before_certification WAIT_FOR continue'; --send INSERT INTO t values (1); --connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 --connection node_1a SET SESSION wsrep_sync_wait = 0; ---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: wsrep_before_replication' +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: wsrep_before_certification' --source include/wait_condition.inc --connection node_2 diff --git a/mysql-test/suite/galera/t/mysql-wsrep#332.test b/mysql-test/suite/galera/t/mysql-wsrep#332.test index 2da01ba900e..674a5c3de52 100644 --- a/mysql-test/suite/galera/t/mysql-wsrep#332.test +++ b/mysql-test/suite/galera/t/mysql-wsrep#332.test @@ -1,7 +1,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 # Open connection node_1a here, MW-369.inc will use it later --connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 diff --git a/mysql-test/suite/galera/t/partition.test b/mysql-test/suite/galera/t/partition.test index 0159ef8f607..13e09a4e3e6 100644 --- a/mysql-test/suite/galera/t/partition.test +++ b/mysql-test/suite/galera/t/partition.test @@ -134,9 +134,12 @@ CREATE TABLE t1 (pk INT PRIMARY KEY) SELECT COUNT(*) 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; @@ -167,7 +170,7 @@ SELECT COUNT(*) 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; @@ -196,9 +199,12 @@ CREATE TABLE t1 (pk INT PRIMARY KEY) --source include/wait_condition.inc SELECT COUNT(*) 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..0ec30829982 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,4 @@ let $start_pos= `select @binlog_start_pos`; # Cleanup DROP TABLE t1; ---source include/galera_end.inc --echo # End of test 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_2x3nodes.cnf b/mysql-test/suite/galera_3nodes/galera_2x3nodes.cnf index 3f39b82f7b7..39a68d2be41 100644 --- a/mysql-test/suite/galera_3nodes/galera_2x3nodes.cnf +++ b/mysql-test/suite/galera_3nodes/galera_2x3nodes.cnf @@ -10,7 +10,6 @@ default-storage-engine=innodb wsrep_gtid_mode=1 gtid_ignore_duplicates -wsrep-on=1 wsrep-provider=@ENV.WSREP_PROVIDER wsrep_node_address=127.0.0.1 # enforce read-committed characteristics across the cluster @@ -21,6 +20,7 @@ wsrep_node_address=127.0.0.1 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port +wsrep-on=1 wsrep-cluster-address='gcomm://' wsrep_provider_options='base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT300S;evs.inactive_timeout=PT1000M;evs.install_timeout=PT155S;evs.keepalive_period = PT100S' @@ -32,6 +32,7 @@ wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port +wsrep-on=1 wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' wsrep_provider_options='base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT300S;evs.inactive_timeout=PT1000M;evs.install_timeout=PT155S;evs.keepalive_period = PT100S' @@ -43,6 +44,7 @@ wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port +wsrep-on=1 wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' wsrep_provider_options='base_port=@mysqld.3.#galera_port;evs.suspect_timeout=PT300S;evs.inactive_timeout=PT1000M;evs.install_timeout=PT155S;evs.keepalive_period = PT100S' @@ -56,7 +58,7 @@ wsrep_cluster_name=cluster2 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port - +wsrep-on=1 wsrep-cluster-address='gcomm://' wsrep_provider_options='base_port=@mysqld.4.#galera_port;evs.suspect_timeout=PT300S;evs.inactive_timeout=PT1000M;evs.install_timeout=PT155S;evs.keepalive_period = PT100S' @@ -69,6 +71,7 @@ wsrep_cluster_name=cluster2 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port +wsrep-on=1 wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.4.#galera_port' wsrep_provider_options='base_port=@mysqld.5.#galera_port;evs.suspect_timeout=PT300S;evs.inactive_timeout=PT1000M;evs.install_timeout=PT155S;evs.keepalive_period = PT100S' @@ -81,6 +84,7 @@ wsrep_cluster_name=cluster2 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port +wsrep-on=1 wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.4.#galera_port' wsrep_provider_options='base_port=@mysqld.6.#galera_port;evs.suspect_timeout=PT300S;evs.inactive_timeout=PT1000M;evs.install_timeout=PT155S;evs.keepalive_period = PT100S' @@ -106,17 +110,3 @@ NODE_MYSOCK_5= @mysqld.5.socket NODE_MYPORT_6= @mysqld.6.port NODE_MYSOCK_6= @mysqld.6.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_GALERAPORT_5= @mysqld.5.#galera_port -NODE_GALERAPORT_6= @mysqld.6.#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 -NODE_SSTPORT_5= @mysqld.5.#sst_port -NODE_SSTPORT_6= @mysqld.6.#sst_port diff --git a/mysql-test/suite/galera_3nodes/galera_3nodes.cnf b/mysql-test/suite/galera_3nodes/galera_3nodes.cnf index 91aa53ad7b1..708902fd7e7 100644 --- a/mysql-test/suite/galera_3nodes/galera_3nodes.cnf +++ b/mysql-test/suite/galera_3nodes/galera_3nodes.cnf @@ -6,7 +6,6 @@ binlog-format=row innodb-autoinc-lock-mode=2 default-storage-engine=innodb -wsrep-on=1 wsrep-provider=@ENV.WSREP_PROVIDER wsrep_node_address=127.0.0.1 # enforce read-committed characteristics across the cluster @@ -17,6 +16,8 @@ wsrep-sync-wait=15 #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port +#wsrep-new-cluster +wsrep-on=1 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' @@ -28,6 +29,7 @@ wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port +wsrep-on=1 wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' wsrep_provider_options='base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S' @@ -39,6 +41,7 @@ wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port +wsrep-on=1 wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' wsrep_provider_options='base_port=@mysqld.3.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S' @@ -55,12 +58,3 @@ 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/include/galera_resume.inc b/mysql-test/suite/galera_3nodes/include/galera_resume.inc index 232cb46479e..af8f2b956fd 100644 --- a/mysql-test/suite/galera/include/galera_resume.inc +++ b/mysql-test/suite/galera_3nodes/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_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/include/have_ipv6.inc b/mysql-test/suite/galera_3nodes/include/have_ipv6.inc deleted file mode 100644 index 560cad03350..00000000000 --- a/mysql-test/suite/galera_3nodes/include/have_ipv6.inc +++ /dev/null @@ -1,15 +0,0 @@ -# Check if ipv6 is available. -# ---disable_query_log ---disable_result_log -connect (checkcon123456789,::1,root,,test); -if($mysql_errno) -{ - skip No IPv6 support; -} -connection default; -disconnect checkcon123456789; ---enable_result_log ---enable_query_log -# end check - diff --git a/mysql-test/suite/galera_3nodes/r/GAL-501.result b/mysql-test/suite/galera_3nodes/r/GAL-501.result index a2bf5f4d98c..063e88ec21a 100644 --- a/mysql-test/suite/galera_3nodes/r/GAL-501.result +++ b/mysql-test/suite/galera_3nodes/r/GAL-501.result @@ -1,12 +1,18 @@ +connection node_2; +connection node_1; +connection node_3; SELECT VARIABLE_VALUE LIKE '%[::1]%' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_incoming_addresses'; VARIABLE_VALUE LIKE '%[::1]%' 1 SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 3 1 +connection node_2; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +connection node_1; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); +connection node_2; SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; SELECT COUNT(*) = 1 FROM t1; COUNT(*) = 1 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 e1528c6f74f..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; @@ -11,6 +13,7 @@ connection node_3; INSERT INTO t2 VALUES (1); connection node_1; COMMIT; -ERROR 40001: Deadlock: wsrep aborted transaction +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_evs_suspect_timeout.result b/mysql-test/suite/galera_3nodes/r/galera_evs_suspect_timeout.result index 7e0d282ec7f..3543feff78c 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_evs_suspect_timeout.result +++ b/mysql-test/suite/galera_3nodes/r/galera_evs_suspect_timeout.result @@ -1,12 +1,19 @@ +connection node_2; +connection node_1; +connection node_1; SET GLOBAL wsrep_provider_options = 'evs.inactive_timeout=PT100M; evs.suspect_timeout=PT1S'; +connection node_2; SET GLOBAL wsrep_provider_options = 'evs.inactive_timeout=PT100M; evs.suspect_timeout=PT1S'; +connection node_3; Suspending node ... +connection node_1; SET SESSION wsrep_sync_wait = 0; SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 2 1 CREATE TABLE t1 (f1 INTEGER); INSERT INTO t1 VALUES (1); +connection node_2; SET SESSION wsrep_sync_wait = 0; SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 2 @@ -16,5 +23,6 @@ SELECT COUNT(*) = 1 FROM t1; COUNT(*) = 1 1 DROP TABLE t1; +connection node_3; Resuming node ... CALL mtr.add_suppression("WSREP: gcs_caused() returned -1 \\(Operation not permitted\\)"); diff --git a/mysql-test/suite/galera_3nodes/r/galera_garbd.result b/mysql-test/suite/galera_3nodes/r/galera_garbd.result index 180aade029c..88bb3ca2ff9 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_garbd.result +++ b/mysql-test/suite/galera_3nodes/r/galera_garbd.result @@ -1,17 +1,31 @@ +connection node_2; +connection node_1; +connection node_1; +connection node_2; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_3; Killing node #3 to free ports for garbd ... +connection node_1; Starting garbd ... CREATE TABLE t1 (f1 INTEGER); INSERT INTO t1 VALUES (1); +connection node_2; SELECT COUNT(*) = 1 FROM t1; COUNT(*) = 1 1 Killing garbd ... +connection node_1; INSERT INTO t1 VALUES (2); +connection node_2; SELECT COUNT(*) = 2 FROM t1; COUNT(*) = 2 1 DROP TABLE t1; Restarting node #3 to satisfy MTR's end-of-test checks +connection node_3; +connection node_1; CALL mtr.add_suppression("WSREP: Protocol violation\. JOIN message sender 1\.0 \(.*\) is not in state transfer \(SYNCED\)"); +connection node_2; CALL mtr.add_suppression("WSREP: Protocol violation\. JOIN message sender 1\.0 \(.*\) is not in state transfer \(SYNCED\)"); +connection node_3; CALL mtr.add_suppression("WSREP: Protocol violation\. JOIN message sender 1\.0 \(.*\) is not in state transfer \(SYNCED\)"); diff --git a/mysql-test/suite/galera_3nodes/r/galera_innobackupex_backup.result b/mysql-test/suite/galera_3nodes/r/galera_innobackupex_backup.result deleted file mode 100644 index 85000db8e77..00000000000 --- a/mysql-test/suite/galera_3nodes/r/galera_innobackupex_backup.result +++ /dev/null @@ -1,11 +0,0 @@ -CREATE TABLE t1 (f1 INTEGER); -INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); -SELECT COUNT(*) = 10 FROM t1; -COUNT(*) = 10 -1 -Killing server ... -INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20); -SELECT COUNT(*) = 20 FROM t1; -COUNT(*) = 20 -1 -DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes/r/galera_ipv6_mysqldump.result b/mysql-test/suite/galera_3nodes/r/galera_ipv6_mysqldump.result index f519654952b..a977f784e54 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_ipv6_mysqldump.result +++ b/mysql-test/suite/galera_3nodes/r/galera_ipv6_mysqldump.result @@ -1,10 +1,22 @@ +connection node_2; +connection node_1; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_1; +connection node_2; +connection node_3; +connection node_1; +CREATE USER 'sst'; GRANT ALL PRIVILEGES ON *.* TO 'sst'; SET GLOBAL wsrep_sst_auth = 'sst:'; +connection node_2; SET GLOBAL wsrep_sst_method = 'mysqldump'; +connection node_2; Unloading wsrep provider ... SET GLOBAL wsrep_provider = 'none'; +connection node_1; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); +connection node_2; Loading wsrep provider ... SELECT COUNT(*) = 1 FROM t1; COUNT(*) = 1 @@ -13,14 +25,16 @@ DROP TABLE t1; SELECT VARIABLE_VALUE LIKE '%[::1]%' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_incoming_addresses'; VARIABLE_VALUE LIKE '%[::1]%' 1 +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; +connection node_2; 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"); +CALL mtr.add_suppression("Table \'mysql.gtid_slave_pos\' doesn\'t exist"); +connection node_2; CALL mtr.add_suppression("Unsupported protocol downgrade: incremental data collection disabled. Expect abort"); diff --git a/mysql-test/suite/galera_3nodes/r/galera_ipv6_rsync.result b/mysql-test/suite/galera_3nodes/r/galera_ipv6_rsync.result index a2bf5f4d98c..3f810d3eb97 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_ipv6_rsync.result +++ b/mysql-test/suite/galera_3nodes/r/galera_ipv6_rsync.result @@ -1,12 +1,17 @@ +connection node_2; +connection node_1; SELECT VARIABLE_VALUE LIKE '%[::1]%' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_incoming_addresses'; VARIABLE_VALUE LIKE '%[::1]%' 1 SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 3 1 +connection node_2; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +connection node_1; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); +connection node_2; SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; SELECT COUNT(*) = 1 FROM t1; COUNT(*) = 1 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 deleted file mode 100644 index 53e35939a79..00000000000 --- a/mysql-test/suite/galera_3nodes/r/galera_ipv6_xtrabackup-v2.result +++ /dev/null @@ -1,18 +0,0 @@ -SELECT VARIABLE_VALUE LIKE '%[::1]%' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_incoming_addresses'; -VARIABLE_VALUE LIKE '%[::1]%' -1 -SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; -VARIABLE_VALUE = 3 -1 -SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; -INSERT INTO t1 VALUES (1); -SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; -SELECT COUNT(*) = 1 FROM t1; -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_parallel_apply_3nodes.result b/mysql-test/suite/galera_3nodes/r/galera_parallel_apply_3nodes.result index 4f9951c382f..8211fb8501e 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_parallel_apply_3nodes.result +++ b/mysql-test/suite/galera_3nodes/r/galera_parallel_apply_3nodes.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_3; @@ -12,7 +14,7 @@ connection node_3; SELECT f1 = 111 FROM t1; f1 = 111 1 -SELECT COUNT(*) IN (1, 2) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'committed%'; +SELECT COUNT(*) IN (1, 2) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%committed%'; COUNT(*) IN (1, 2) 1 SET GLOBAL wsrep_slave_threads = 1;; 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 9f845ffe776..3ae983f9550 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result +++ b/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result @@ -1,9 +1,15 @@ +connection node_2; +connection node_1; +connection node_1; SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_weight'; VARIABLE_VALUE = 3 +1 SET GLOBAL wsrep_provider_options = 'pc.weight=3'; SELECT VARIABLE_VALUE = 5 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_weight'; VARIABLE_VALUE = 5 +1 SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; +connection node_2; SET SESSION wsrep_sync_wait=0; SET SESSION wsrep_on=OFF; SET SESSION wsrep_on=ON; @@ -12,6 +18,7 @@ Variable_name Value wsrep_cluster_size 2 SHOW STATUS LIKE 'wsrep_cluster_weight'; Variable_name Value +wsrep_cluster_weight 0 SHOW STATUS LIKE 'wsrep_cluster_status'; Variable_name Value wsrep_cluster_status non-Primary @@ -27,6 +34,7 @@ wsrep_local_state 0 SHOW STATUS LIKE 'wsrep_local_state_comment'; Variable_name Value wsrep_local_state_comment Initialized +connection node_3; SET SESSION wsrep_sync_wait=0; SET SESSION wsrep_on=OFF; SET SESSION wsrep_on=ON; @@ -35,6 +43,7 @@ Variable_name Value wsrep_cluster_size 2 SHOW STATUS LIKE 'wsrep_cluster_weight'; Variable_name Value +wsrep_cluster_weight 0 SHOW STATUS LIKE 'wsrep_cluster_status'; Variable_name Value wsrep_cluster_status non-Primary @@ -50,8 +59,10 @@ wsrep_local_state 0 SHOW STATUS LIKE 'wsrep_local_state_comment'; Variable_name Value wsrep_local_state_comment Initialized +connection node_1; SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_weight'; VARIABLE_VALUE = 3 +1 SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; VARIABLE_VALUE = 'Primary' 1 @@ -70,12 +81,18 @@ VARIABLE_VALUE = 'Synced' SET GLOBAL wsrep_provider_options = 'pc.weight=1'; SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_weight'; VARIABLE_VALUE = 1 +1 +connection node_1; SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; +connection node_2; +connection node_3; +connection node_1; SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 3 1 SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_weight'; VARIABLE_VALUE = 3 +1 SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; VARIABLE_VALUE = 'Primary' 1 @@ -91,11 +108,13 @@ VARIABLE_VALUE = 4 SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; VARIABLE_VALUE = 'Synced' 1 +connection node_2; SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 3 1 SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_weight'; VARIABLE_VALUE = 3 +1 SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; VARIABLE_VALUE = 'Primary' 1 @@ -111,11 +130,13 @@ VARIABLE_VALUE = 4 SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; VARIABLE_VALUE = 'Synced' 1 +connection node_3; SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 3 1 SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_weight'; VARIABLE_VALUE = 3 +1 SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; VARIABLE_VALUE = 'Primary' 1 @@ -131,12 +152,15 @@ VARIABLE_VALUE = 4 SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; VARIABLE_VALUE = 'Synced' 1 +connection node_1; SET GLOBAL wsrep_provider_options = 'pc.weight=1'; 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|Socket is not connected)'); CALL mtr.add_suppression('overriding reported weight for'); diff --git a/mysql-test/suite/galera_3nodes/r/galera_safe_to_bootstrap.result b/mysql-test/suite/galera_3nodes/r/galera_safe_to_bootstrap.result index 21f747d280b..b87c8743406 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_safe_to_bootstrap.result +++ b/mysql-test/suite/galera_3nodes/r/galera_safe_to_bootstrap.result @@ -1,23 +1,46 @@ +connection node_2; +connection node_1; +connection node_1; +connection node_2; +connection node_3; +connection node_1; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] +connection node_2; +connection node_1; include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] +connection node_3; +connection node_1; include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 1'] +connection node_2; +connection node_1; include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] +connection node_2; +connection node_1; SET SESSION wsrep_on = OFF; Killing server ... safe_to_bootstrap: 1 safe_to_bootstrap: 0 safe_to_bootstrap: 0 +connection node_1; +connection node_2; +connection node_3; +connection node_2; CALL mtr.add_suppression("Failed to prepare for incremental state transfer"); +CALL mtr.add_suppression("It may not be safe to bootstrap the cluster from this node"); +CALL mtr.add_suppression("Aborting"); +connection node_3; CALL mtr.add_suppression("Failed to prepare for incremental state transfer"); +CALL mtr.add_suppression("It may not be safe to bootstrap the cluster from this node"); +CALL mtr.add_suppression("Aborting"); SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/mysql-test/suite/galera_3nodes/r/galera_var_dirty_reads2.result b/mysql-test/suite/galera_3nodes/r/galera_var_dirty_reads2.result index 88780a2c87f..8e6d27823f6 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_var_dirty_reads2.result +++ b/mysql-test/suite/galera_3nodes/r/galera_var_dirty_reads2.result @@ -1,6 +1,11 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER); INSERT INTO t1 VALUES (1); +connection node_2; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +connection node_1; +connection node_2; SET SESSION wsrep_sync_wait = 0; SET SESSION wsrep_dirty_reads = 1; SELECT f1 FROM t1; @@ -45,4 +50,6 @@ SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.PROCESSLIST; COUNT(*) > 0 1 SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +connection node_1; +connection node_2; DROP TABLE t1; 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..23ced3ba734 --- /dev/null +++ b/mysql-test/suite/galera_3nodes/r/galera_wsrep_schema.result @@ -0,0 +1,82 @@ +connection node_2; +connection node_1; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_1; +connection node_1; +connection node_2; +connection node_3; +SHOW CREATE TABLE mysql.wsrep_cluster; +Table Create Table +wsrep_cluster CREATE TABLE `wsrep_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, + `capabilities` int(11) NOT NULL, + PRIMARY KEY (`cluster_uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE mysql.wsrep_cluster_members; +Table Create Table +wsrep_cluster_members CREATE TABLE `wsrep_cluster_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 mysql.wsrep_cluster; +COUNT(*) = 1 +1 +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM mysql.wsrep_cluster; +cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') +1 +SELECT COUNT(*) = 3 FROM mysql.wsrep_cluster_members; +COUNT(*) = 3 +1 +SELECT COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') FROM mysql.wsrep_cluster_members; +COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') +1 +SELECT COUNT(*) = 1 FROM mysql.wsrep_cluster_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 mysql.wsrep_cluster_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 mysql.wsrep_cluster_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 mysql.wsrep_cluster_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 mysql.wsrep_cluster; +cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') +1 +SELECT COUNT(*) = 2 FROM mysql.wsrep_cluster_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 mysql.wsrep_cluster; +cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') +1 +SELECT COUNT(*) = 3 FROM mysql.wsrep_cluster_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 mysql.wsrep_cluster; +cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') +1 +SELECT COUNT(*) = 3 FROM mysql.wsrep_cluster_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"); +connection node_3; +CALL mtr.add_suppression("SYNC message from member"); diff --git a/mysql-test/suite/galera_3nodes/suite.pm b/mysql-test/suite/galera_3nodes/suite.pm index 3a1237ecf75..03eeeeaf057 100644 --- a/mysql-test/suite/galera_3nodes/suite.pm +++ b/mysql-test/suite/galera_3nodes/suite.pm @@ -9,9 +9,9 @@ return "Not run for embedded server" if $::opt_embedded_server; return "WSREP is not compiled in" unless defined $::mysqld_variables{'wsrep-on'}; my ($provider) = grep { -f $_ } $ENV{WSREP_PROVIDER}, - "/usr/lib64/galera-3/libgalera_smm.so", + "/usr/lib64/galera-4/libgalera_smm.so", "/usr/lib64/galera/libgalera_smm.so", - "/usr/lib/galera-3/libgalera_smm.so", + "/usr/lib/galera-4/libgalera_smm.so", "/usr/lib/galera/libgalera_smm.so"; return "No wsrep provider library" unless -f $provider; diff --git a/mysql-test/suite/galera_3nodes/t/GAL-501.test b/mysql-test/suite/galera_3nodes/t/GAL-501.test index 60ed5989227..c4b17cdb21e 100644 --- a/mysql-test/suite/galera_3nodes/t/GAL-501.test +++ b/mysql-test/suite/galera_3nodes/t/GAL-501.test @@ -5,7 +5,13 @@ # ist.recv_addr=[::1] --source include/galera_cluster.inc ---source include/have_ipv6.inc +--source include/check_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 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..81d927894c7 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_garbd.test +++ b/mysql-test/suite/galera_3nodes/t/galera_garbd.test @@ -7,10 +7,21 @@ --source include/have_innodb.inc --source include/big_test.inc +# Save galera ports +--connection node_1 +--source suite/galera/include/galera_base_port.inc +--let $NODE_GALERAPORT_1 = $_NODE_GALERAPORT + +--connection node_2 +--source suite/galera/include/galera_base_port.inc +--let $NODE_GALERAPORT_2 = $_NODE_GALERAPORT + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--source suite/galera/include/galera_base_port.inc +--let $NODE_GALERAPORT_3 = $_NODE_GALERAPORT + +--connection node_3 --echo Killing node #3 to free ports for garbd ... ---let $galera_connection_name = node_3 ---let $galera_server_number = 3 ---source include/galera_connect.inc --source include/shutdown_mysqld.inc --connection node_1 @@ -32,7 +43,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_innobackupex_backup.test b/mysql-test/suite/galera_3nodes/t/galera_innobackupex_backup.test deleted file mode 100644 index cc3f42c7290..00000000000 --- a/mysql-test/suite/galera_3nodes/t/galera_innobackupex_backup.test +++ /dev/null @@ -1,58 +0,0 @@ -# -# This test uses innobackupex to take a backup on node #2 and then restores that node from backup -# - ---source include/galera_cluster.inc ---source include/have_innodb.inc - ---connection node_1 -CREATE TABLE t1 (f1 INTEGER); -INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); - ---connection node_2 -SELECT COUNT(*) = 10 FROM t1; - ---exec rm -rf $MYSQL_TMP_DIR/innobackupex_backup ---exec innobackupex --defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group=mysqld.2 $MYSQL_TMP_DIR/innobackupex_backup --galera-info --port=$NODE_MYPORT_2 --host=127.0.0.1 --no-timestamp > $MYSQL_TMP_DIR/innobackupex-backup.log ---exec innobackupex --defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group=mysqld.2 $MYSQL_TMP_DIR/innobackupex_backup --apply-log --galera-info --port=$NODE_MYPORT_2 --host=127.0.0.1 --no-timestamp > $MYSQL_TMP_DIR/innobackupex-apply.log - ---source ../galera/include/kill_galera.inc ---sleep 1 - ---connection node_1 -INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20); - ---exec rm -rf $MYSQLTEST_VARDIR/mysqld.2/data/* ---exec innobackupex --defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group=mysqld.2 --copy-back $MYSQL_TMP_DIR/innobackupex_backup --port=$NODE_MYPORT_2 --host=127.0.0.1 > $MYSQL_TMP_DIR/innobackupex-restore.log - -# -# Convert the xtrabackup_galera_info into a grastate.dat file -# - ---perl - use strict; - my $xtrabackup_galera_info_file = $ENV{'MYSQL_TMP_DIR'}.'/innobackupex_backup/xtrabackup_galera_info'; - open(XTRABACKUP_GALERA_INFO, $xtrabackup_galera_info_file) or die "Can not open $xtrabackup_galera_info_file: $!"; - my $xtrabackup_galera_info = <XTRABACKUP_GALERA_INFO>; - my ($uuid, $seqno) = split(':', $xtrabackup_galera_info); - - my $grastate_dat_file = $ENV{'MYSQLTEST_VARDIR'}.'/mysqld.2/data/grastate.dat'; - die "grastate.dat already exists" if -e $grastate_dat_file; - - open(GRASTATE_DAT, ">$grastate_dat_file") or die "Can not write to $grastate_dat_file: $!"; - print GRASTATE_DAT "version: 2.1\n"; - print GRASTATE_DAT "uuid: $uuid\n"; - print GRASTATE_DAT "seqno: $seqno\n"; - print GRASTATE_DAT "cert_index:\n"; - exit(0); -EOF - ---source include/start_mysqld.inc ---sleep 5 - ---source include/wait_until_connected_again.inc -SELECT COUNT(*) = 20 FROM t1; - -DROP TABLE t1; - ---sleep 10 diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.opt b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.opt new file mode 100644 index 00000000000..215293eccec --- /dev/null +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.opt @@ -0,0 +1 @@ +--bind-address=* diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.test b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.test index 5b06e617eef..93050b54f5d 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.test +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.test @@ -1,7 +1,15 @@ --source include/galera_cluster.inc ---source include/have_ipv6.inc +--source include/check_ipv6.inc + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 + # Save original auto_increment_offset values. + --let $node_1=node_1 + --let $node_2=node_2 + --let $node_3=node_3 + --source ../galera/include/auto_increment_offset_save.inc --connection node_1 +CREATE USER 'sst'; GRANT ALL PRIVILEGES ON *.* TO 'sst'; --let $wsrep_sst_auth_orig = `SELECT @@wsrep_sst_auth` @@ -51,6 +59,11 @@ DROP TABLE t1; SELECT VARIABLE_VALUE LIKE '%[::1]%' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_incoming_addresses'; +# restart node so we don't fail on WSREP_START_POSITION internal check +--source include/restart_mysqld.inc +--source include/wait_until_connected_again.inc + +--source ../galera/include/auto_increment_offset_restore.inc --source suite/galera/include/galera_sst_restore.inc --connection node_2 CALL mtr.add_suppression("Unsupported protocol downgrade: incremental data collection disabled. Expect abort"); diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync.test b/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync.test index 7ee209d8e72..1937eb43e13 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync.test +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync.test @@ -1,5 +1,5 @@ --source include/galera_cluster.inc ---source include/have_ipv6.inc +--source include/check_ipv6.inc # Confirm that initial handshake happened over ipv6 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 deleted file mode 100644 index 8a80be0d2a9..00000000000 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.cnf +++ /dev/null @@ -1,26 +0,0 @@ -!include ../galera_3nodes.cnf - -[mysqld] -wsrep_sst_method=xtrabackup-v2 -wsrep_sst_auth="root:" - -[mysqld.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_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_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' -wsrep_node_incoming_address='[::1]:@mysqld.3.port' - -[SST] -sockopt=",pf=ip6" 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 deleted file mode 100644 index 84eee017700..00000000000 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_xtrabackup-v2.test +++ /dev/null @@ -1,62 +0,0 @@ ---source include/galera_cluster.inc ---source include/have_ipv6.inc - -# Confirm that initial handshake happened over ipv6 - -SELECT VARIABLE_VALUE LIKE '%[::1]%' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_incoming_addresses'; -SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; - -# Force IST - ---connection node_2 -SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; - ---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 - -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; -INSERT INTO t1 VALUES (1); - ---connection node_2 -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 = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; ---source include/wait_condition.inc - -SELECT COUNT(*) = 1 FROM t1; - -DROP TABLE t1; - -# Confirm that key messages around SST and IST reference IPv6 - ---connection node_1 ---let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.1.err ---let $assert_only_after = CURRENT_TEST - ---let $assert_count = 2 ---let $assert_text = Streaming the backup to joiner at \[::1\] ---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 - - - - 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_parallel_apply_3nodes.test b/mysql-test/suite/galera_3nodes/t/galera_parallel_apply_3nodes.test index 7d80d8036a1..659df2b3c93 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_parallel_apply_3nodes.test +++ b/mysql-test/suite/galera_3nodes/t/galera_parallel_apply_3nodes.test @@ -31,7 +31,7 @@ SET GLOBAL wsrep_slave_threads = 2; --connection node_3 SELECT f1 = 111 FROM t1; -SELECT COUNT(*) IN (1, 2) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE 'committed%'; +SELECT COUNT(*) IN (1, 2) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%committed%'; --eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig; 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 0a94e7cd85d..729f14a731f 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 SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_weight'; @@ -55,6 +55,9 @@ SHOW STATUS LIKE 'wsrep_local_state_comment'; --connection node_1 # 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 diff --git a/mysql-test/suite/galera_3nodes/t/galera_safe_to_bootstrap.test b/mysql-test/suite/galera_3nodes/t/galera_safe_to_bootstrap.test index 88d0cfba4f4..722242b22c8 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_safe_to_bootstrap.test +++ b/mysql-test/suite/galera_3nodes/t/galera_safe_to_bootstrap.test @@ -3,6 +3,22 @@ # --source include/galera_cluster.inc + +# +# Create connection node_3 and save auto increment variables. +# +--let $galera_connection_name = node_3 +--let $galera_server_number = 3 +--source include/galera_connect.inc + +--let $node_1 = node_1 +--let $node_2 = node_2 +--let $node_3 = node_3 + +--source ../galera/include/auto_increment_offset_save.inc + +--connection node_1 + CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; # @@ -48,7 +64,6 @@ CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; # Shut down one more node # ---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 --connection node_3 --source include/shutdown_mysqld.inc @@ -155,9 +170,18 @@ SET SESSION wsrep_on = OFF; --connection node_2 CALL mtr.add_suppression("Failed to prepare for incremental state transfer"); +CALL mtr.add_suppression("It may not be safe to bootstrap the cluster from this node"); +CALL mtr.add_suppression("Aborting"); --connection node_3 CALL mtr.add_suppression("Failed to prepare for incremental state transfer"); +CALL mtr.add_suppression("It may not be safe to bootstrap the cluster from this node"); +CALL mtr.add_suppression("Aborting"); SHOW CREATE TABLE t1; DROP TABLE t1; + +# +# Restore auto increment variables. +# +--source ../galera/include/auto_increment_offset_restore.inc 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_var_dirty_reads2.test b/mysql-test/suite/galera_3nodes/t/galera_var_dirty_reads2.test index 129ba2e1f38..2ceda1ed352 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_var_dirty_reads2.test +++ b/mysql-test/suite/galera_3nodes/t/galera_var_dirty_reads2.test @@ -106,7 +106,8 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; --source include/wait_condition.inc --connection node_2 ---let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +--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 DROP TABLE t1; 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..5c2cae75bd0 --- /dev/null +++ b/mysql-test/suite/galera_3nodes/t/galera_wsrep_schema.test @@ -0,0 +1,83 @@ +# +# This test performs basic checks on the contents of the wsrep_schema +# +# wsrep_members_history checks are temporarily disabled until it +# can be made configurable. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_1 +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--let $node_3=node_3 +--source ../galera/include/auto_increment_offset_save.inc + +# Make the test fail if table structure has changed + +SHOW CREATE TABLE mysql.wsrep_cluster; +SHOW CREATE TABLE mysql.wsrep_cluster_members; +#disabled SHOW CREATE TABLE mysql.wsrep_member_history; + +# Checks for the wsrep_cluster table + +SELECT COUNT(*) = 1 FROM mysql.wsrep_cluster; +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM mysql.wsrep_cluster; + +# Checks for the wsrep_cluster_members table + +SELECT COUNT(*) = 3 FROM mysql.wsrep_cluster_members; +SELECT COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') FROM mysql.wsrep_cluster_members; +SELECT COUNT(*) = 1 FROM mysql.wsrep_cluster_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 mysql.wsrep_cluster_members; +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM mysql.wsrep_cluster_members; + +# Checks for the wsrep_cluster_member_history table + +#disabled SELECT COUNT(*) = 3 FROM mysql.wsrep_cluster_member_history; +#disabled SELECT COUNT(*) = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size') FROM mysql.wsrep_cluster_member_history; +SELECT COUNT(*) = 1 FROM mysql.wsrep_cluster_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 mysql.wsrep_cluster) FROM mysql.wsrep_cluster_member_history; +#disabled SELECT last_view_seqno = (SELECT view_seqno FROM mysql.wsrep_cluster) FROM mysql.wsrep_cluster_member_history; +#disabled SELECT node_incoming_address LIKE '127.0.0.1:%' from mysql.wsrep_cluster_member_history; +#disabled SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM mysql.wsrep_cluster_member_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 mysql.wsrep_cluster; +SELECT COUNT(*) = 2 FROM mysql.wsrep_cluster_members; +#disabled SELECT COUNT(*) = 3 FROM mysql.wsrep_cluster_member_history; +#disabled SELECT COUNT(*) = 2 FROM mysql.wsrep_cluster_member_history WHERE last_view_id = (SELECT MAX(last_view_id) FROM mysql.wsrep_cluster_member_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 mysql.wsrep_cluster; +SELECT COUNT(*) = 3 FROM mysql.wsrep_cluster_members; +#disabled SELECT COUNT(*) = 3 FROM mysql.wsrep_cluster_member_history WHERE last_view_id = (SELECT MAX(last_view_id) FROM mysql.wsrep_cluster_member_history); + +--connection node_1 +SELECT cluster_uuid = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_state_uuid') FROM mysql.wsrep_cluster; +SELECT COUNT(*) = 3 FROM mysql.wsrep_cluster_members; +#disabled SELECT COUNT(*) = 3 FROM mysql.wsrep_cluster_member_history WHERE last_view_id = (SELECT MAX(last_view_id) FROM mysql.wsrep_cluster_member_history); + +--source ../galera/include/auto_increment_offset_restore.inc + +--connection node_1 +CALL mtr.add_suppression("SYNC message from member"); + +--connection node_2 +CALL mtr.add_suppression("SYNC message from member"); + +--connection node_3 +CALL mtr.add_suppression("SYNC message from member"); 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..bb6c11edf36 --- /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 mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; +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..9e2a4823973 --- /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 mysql.wsrep_streaming_log; +COUNT(*) +5 +SELECT COUNT(*) FROM mysql.wsrep_streaming_log; +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..775f7ee0412 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-606.result @@ -0,0 +1,38 @@ +connection node_2; +connection node_1; +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; +connection node_2a; +SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +SET WSREP_ON=ON; +connection node_1; +connection node_2a; +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +connection node_1; +connection node_1; +SELECT COUNT(DISTINCT node_uuid) = 1 FROM mysql.wsrep_streaming_log; +COUNT(DISTINCT node_uuid) = 1 +0 +connection node_2; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT * FROM t1; +f1 +COMMIT; +connection node_1; +SELECT * FROM t1; +f1 +DROP TABLE t1; +connection node_2; +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..8fe13c7e2bf --- /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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +0 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..9a83ff3c041 --- /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 mysql.wsrep_streaming_log; +COUNT(DISTINCT node_uuid) = 1 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(DISTINCT node_uuid) = 1 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(DISTINCT node_uuid) = 1 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(DISTINCT node_uuid) = 1 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(DISTINCT node_uuid) = 1 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'primary'; +COUNT(*) = 0 +1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..bbec3531a49 --- /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 mysql.wsrep_streaming_log; +COUNT(DISTINCT node_uuid) = 1 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(DISTINCT node_uuid) = 1 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f1 = 'secondary'; +COUNT(*) = 0 +1 +SELECT COUNT(DISTINCT node_uuid) = 1 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..1a6dcbfd392 --- /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 mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT * FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT * FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT * FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT * FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT * FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT * FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT * FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT * FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +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..4eb0ebca4f4 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-817.result @@ -0,0 +1,54 @@ +connection node_2; +connection node_1; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_1; +connection node_2; +connection node_3; +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 mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +connection node_2; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; +SET SESSION wsrep_on = OFF; +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +connection node_2; +connection node_3; +connection node_1a; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; +connection node_3; +connection node_1a; +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_1; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +connection node_1a; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +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..d670b8c24a0 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-832.result @@ -0,0 +1,26 @@ +connection node_2; +connection node_1; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_1; +connection node_2; +connection node_3; +connection node_2; +SET GLOBAL debug="d,crash_last_fragment_commit_after_fragment_removal"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +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 +connection node_1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..bb4eb829abc --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_isolate_master.result @@ -0,0 +1,80 @@ +connection node_2; +connection node_1; +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 mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +connection node_2; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) > 0 FROM t1; +COUNT(*) > 0 +1 +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; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_2; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +connection node_3; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +connection node_1a; +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +connection node_2; +connection node_3; +connection node_1a; +connection node_1; +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 mysql.wsrep_streaming_log; +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; +connection node_2; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_3; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +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/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..0260ebec86a --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_join_slave.result @@ -0,0 +1,39 @@ +connection node_2; +connection node_1; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_1; +connection node_1; +connection node_2; +connection node_3; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +connection node_2; +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; +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; +COUNT(*) = 10 +1 +connection node_2; +SELECT COUNT(*) = 10 FROM t1; +COUNT(*) = 10 +1 +connection node_3; +SELECT COUNT(*) = 10 FROM t1; +COUNT(*) = 10 +1 +connection node_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..1a179565666 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_master.result @@ -0,0 +1,33 @@ +connection node_2; +connection node_1; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_1; +connection node_2; +connection node_3; +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); +connection node_3; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +connection node_2; +Killing server ... +connection node_3; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +INSERT INTO t1 VALUES (1); +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..595bd30d675 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply.result @@ -0,0 +1,53 @@ +connection node_2; +connection node_1; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_1; +connection node_2; +connection node_3; +connection node_1; +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; +Killing server ... +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; +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; +SELECT COUNT(*) = 15 FROM mysql.wsrep_streaming_log; +COUNT(*) = 15 +1 +connection node_1; +COMMIT; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SELECT COUNT(*) = 15 FROM t1; +COUNT(*) = 15 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +DROP TABLE t1; +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/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..239eb748385 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_after_apply_rollback.result @@ -0,0 +1,58 @@ +connection node_2; +connection node_1; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_1; +connection node_2; +connection node_3; +connection node_1; +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; +Killing server ... +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; +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; +SELECT COUNT(*) = 15 FROM mysql.wsrep_streaming_log; +COUNT(*) = 15 +1 +connection node_1; +ROLLBACK; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..21e301ed353 --- /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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..4a135cd9274 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_kill_slave_before_apply.result @@ -0,0 +1,44 @@ +connection node_2; +connection node_1; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_1; +connection node_2; +connection node_3; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +connection node_2; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +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; +Killing server ... +connection node_1; +COMMIT; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +connection node_2; +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_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..1a50bace279 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/r/galera_sr_threeway_split.result @@ -0,0 +1,117 @@ +connection node_2; +connection node_1; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_1; +connection node_2; +connection node_3; +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 (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 mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +connection node_2; +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); +connection node_3; +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; +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; +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_2a; +SET SESSION wsrep_on = ON; +SET SESSION wsrep_sync_wait = 15; +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +connection node_3a; +SET SESSION wsrep_on = ON; +SET SESSION wsrep_sync_wait = 15; +SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +connection node_1a; +connection node_2a; +connection node_3a; +connection node_2; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(DISTINCT node_uuid) = 1 FROM mysql.wsrep_streaming_log; +COUNT(DISTINCT node_uuid) = 1 +1 +wsrep_gcomm_uuid_match +1 +connection node_3; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(DISTINCT node_uuid) = 1 FROM mysql.wsrep_streaming_log; +COUNT(DISTINCT node_uuid) = 1 +1 +wsrep_gcomm_uuid_match +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; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +connection node_2; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=ON; +connection node_3; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +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 "); 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..b8d46db74f1 --- /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 mysql.wsrep_streaming_log; + +--connection node_1 +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; +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..bf19ea84c87 --- /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 mysql.wsrep_streaming_log; + +--connection node_1 +SELECT COUNT(*) FROM mysql.wsrep_streaming_log; +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..6d49247ab5e --- /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 mysql.wsrep_streaming_log +--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 mysql.wsrep_streaming_log; +--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 mysql.wsrep_streaming_log; + +--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 "); 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..fd346cf365b --- /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 mysql.wsrep_streaming_log; + +--connection node_1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..a32da959429 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-817.test @@ -0,0 +1,109 @@ +# +# GCF-817 SR: master removes SR trx in non-primary view +# + +--source include/galera_cluster.inc + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--let $node_3=node_3 +--source ../galera/include/auto_increment_offset_save.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 mysql.wsrep_streaming_log; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; +--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 mysql.wsrep_streaming_log; + +--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 mysql.wsrep_streaming_log +--source include/wait_condition.inc + +--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 mysql.wsrep_streaming_log +--source include/wait_condition.inc + +--connection node_2 +# And none on slave +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +--connection node_1 +--error ER_LOCK_DEADLOCK +COMMIT; + +# SR table is now empty everywhere +--connection node_1a +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +--connection node_2 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +--connection node_2 +DROP TABLE t1; + +--source ../galera/include/auto_increment_offset_restore.inc 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..c5a6346d6a1 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-832.test @@ -0,0 +1,43 @@ +# +# GCF-832 SR: mysql.wsrep_streaming_log 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 +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--let $node_3=node_3 +--source ../galera/include/auto_increment_offset_save.inc + +--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 mysql.wsrep_streaming_log; + +--connection node_2 +--enable_reconnect +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +DROP TABLE t1; + +--source ../galera/include/auto_increment_offset_restore.inc 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..0944abd0ad5 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/disabled.def @@ -0,0 +1,7 @@ +GCF-336 : +GCF-582 : +GCF-609 : +GCF-810A : +GCF-810B : +GCF-810C : +galera_sr_kill_slave_after_apply_rollback2 :
\ No newline at end of file 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..30fd0192f26 --- /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 mysql.wsrep_streaming_log; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log +--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 mysql.wsrep_streaming_log tables +# + +--connection node_2 +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +--source include/wait_condition.inc +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +SELECT COUNT(*) = 0 FROM t1; + +--connection node_3 +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--let $wait_condition = SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +--source include/wait_condition.inc +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +--source include/wait_condition.inc + +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +# +# 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 mysql.wsrep_streaming_log; +--source include/wait_condition.inc +SELECT COUNT(*) = 5 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +--connection node_3 +--let $wait_condition = SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +--source include/wait_condition.inc +SELECT COUNT(*) = 5 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +--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..95aa1a37a78 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_join_slave.test @@ -0,0 +1,59 @@ +# +# 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 + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connection node_1 +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--let $node_3=node_3 +--source ../galera/include/auto_increment_offset_save.inc + +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 + +--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; + +--connection node_3 +SELECT COUNT(*) = 10 FROM t1; + +--connection node_1 +DROP TABLE t1; + +--source ../galera/include/auto_increment_offset_restore.inc 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..c7e7528679b --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_master.test @@ -0,0 +1,58 @@ +# +# This test kills the master while a Streaming Replication transaction is in progress +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--let $node_3=node_3 +--source ../galera/include/auto_increment_offset_save.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); + +--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 mysql.wsrep_streaming_log; +--source include/wait_condition.inc + +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +# and we can insert them again +INSERT INTO t1 VALUES (1); + +--connection node_2 +--source include/start_mysqld.inc + +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +SELECT COUNT(*) = 1 FROM t1; + +DROP TABLE t1; + +--source ../galera/include/auto_increment_offset_restore.inc 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..270af538085 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply.test @@ -0,0 +1,81 @@ +# +# 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 + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--let $node_3=node_3 +--source ../galera/include/auto_increment_offset_save.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 + +--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 + +--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 mysql.wsrep_streaming_log; + +--connection node_1 +COMMIT; + +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SELECT COUNT(*) = 15 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +DROP TABLE t1; + +--connection node_3 +CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member"); + +--source ../galera/include/auto_increment_offset_restore.inc 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..c0df6b2777a --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_after_apply_rollback.test @@ -0,0 +1,80 @@ +# +# 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 + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--let $node_3=node_3 +--source ../galera/include/auto_increment_offset_save.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 + +--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 + +--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 mysql.wsrep_streaming_log; + +--connection node_1 +ROLLBACK; + +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +DROP TABLE t1; + +--source ../galera/include/auto_increment_offset_restore.inc 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..83964769ef5 --- /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 mysql.wsrep_streaming_log; + +--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 mysql.wsrep_streaming_log; + +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +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..92566fa6323 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_kill_slave_before_apply.test @@ -0,0 +1,73 @@ +# +# 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 + + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--let $node_3=node_3 +--source ../galera/include/auto_increment_offset_save.inc + +--connection node_1 +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 +--source include/start_mysqld.inc + +# Expect that the SR table will get some entries after the restart +--let $wait_condition = SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; +--source include/wait_condition.inc + +--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 mysql.wsrep_streaming_log; + +--connection node_1 +DROP TABLE t1; +DROP TABLE t2; + +--source ../galera/include/auto_increment_offset_restore.inc 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..62122fe4292 --- /dev/null +++ b/mysql-test/suite/galera_3nodes_sr/t/galera_sr_threeway_split.test @@ -0,0 +1,177 @@ +# +# 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 + +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--let $node_3=node_3 +--source ../galera/include/auto_increment_offset_save.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 mysql.wsrep_streaming_log; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log +--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); + +--connection node_3 +--let $wait_condition = SELECT COUNT(DISTINCT node_uuid) = 2 FROM mysql.wsrep_streaming_log +--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 mysql.wsrep_streaming_log +--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 mysql.wsrep_streaming_log; +--disable_query_log +--eval SELECT DISTINCT node_uuid = '$node_1_gcomm_uuid' AS wsrep_gcomm_uuid_match FROM mysql.wsrep_streaming_log; +--enable_query_log + +--connection node_3 +--error ER_LOCK_DEADLOCK +COMMIT; +SELECT COUNT(DISTINCT node_uuid) = 1 FROM mysql.wsrep_streaming_log; +--disable_query_log +--eval SELECT DISTINCT node_uuid = '$node_1_gcomm_uuid' AS wsrep_gcomm_uuid_match FROM mysql.wsrep_streaming_log; +--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 mysql.wsrep_streaming_log; +SET AUTOCOMMIT=ON; + +--connection node_2 +COMMIT; +SELECT COUNT(*) = 15, MIN(f1) = 10, MAX(f1) = 34 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +SET AUTOCOMMIT=ON; + +--connection node_3 +COMMIT; +SELECT COUNT(*) = 15, MIN(f1) = 10, MAX(f1) = 34 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 "); + +--source ../galera/include/auto_increment_offset_restore.inc 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..541ac3cddfb --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-1008.result @@ -0,0 +1,70 @@ +connection node_2; +connection node_1; +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2; +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; +SET GLOBAL wsrep_provider_options = 'dbug=d,before_local_commit_monitor_enter'; +connection node_2; +COMMIT; +connection node_2b; +SET SESSION wsrep_sync_wait = 0; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +connection node_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'); +connection node_2b; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +connection node_2a; +SET GLOBAL wsrep_provider_options = 'signal=before_local_commit_monitor_enter'; +SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_2; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +DROP TABLE t1; +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; +SET GLOBAL wsrep_provider_options = 'dbug=d,before_certify_apply_monitor_enter'; +connection node_2; +COMMIT; +connection node_2b; +SET SESSION wsrep_sync_wait = 0; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +connection node_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'); +connection node_2b; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +connection node_2a; +SET GLOBAL wsrep_provider_options = 'signal=before_certify_apply_monitor_enter'; +SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_2; +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..ec5bdca214c --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-1018.result @@ -0,0 +1,24 @@ +connection node_2; +connection node_1; +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; +SET GLOBAL wsrep_provider_options = 'dbug=d,after_certify_apply_monitor_enter'; +connection node_2; +SET SESSION wsrep_trx_fragment_size = 64; +DELETE FROM t1 ORDER BY f1 DESC LIMIT 2;; +connection node_2a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +connection node_1; +INSERT INTO t1 (f2) VALUES ('d'),('e'); +connection node_2a; +SET GLOBAL wsrep_provider_options = 'signal=after_certify_apply_monitor_enter'; +SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_2; +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..4752c072cc1 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-1018B.result @@ -0,0 +1,12 @@ +connection node_2; +connection node_1; +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; +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..cc90461291d --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-1043A.result @@ -0,0 +1,21 @@ +connection node_2; +connection node_1; +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +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') +connection node_1; +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;;; +connection node_1a; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_trx_fragment_size = 1;;; +connection node_2; +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..a10295c00b9 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-1043B.result @@ -0,0 +1,21 @@ +connection node_2; +connection node_1; +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +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; +connection node_1; +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;;; +connection node_1a; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_trx_fragment_size = 1;;; +connection node_2; +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..82fa389bb1d --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-1051.result @@ -0,0 +1,46 @@ +connection node_2; +connection node_1; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size=1; +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; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +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; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..58af97d064b --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-1060.result @@ -0,0 +1,21 @@ +connection node_2; +connection node_1; +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +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'); +connection node_1; +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;;; +connection node_1a; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_trx_fragment_size = 1;;; +connection node_2; +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..1aa0c9c0768 --- /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 mysql.wsrep_streaming_log: 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..58663caf134 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-561.result @@ -0,0 +1,50 @@ +connection node_2; +connection node_1; +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; +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +ALTER TABLE t1 DROP COLUMN f2; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_1; +INSERT INTO t1 VALUES (6, 6); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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); +connection node_2; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +connection node_1; +COMMIT; +connection node_2; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..4b4f749d910 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-571.result @@ -0,0 +1,67 @@ +connection node_2; +connection node_1; +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 mysql.wsrep_streaming_log WHERE frag LIKE '%abcdef%'; +COUNT(*) > 0 +1 +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log WHERE frag LIKE '%xyz%'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 1 FROM mysql.wsrep_streaming_log WHERE frag LIKE '%SAVEPOINT `A`%'; +COUNT(*) = 1 +0 +connection node_1; +ROLLBACK TO SAVEPOINT A; +connection node_1a; +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log WHERE frag LIKE '%abcdef%'; +COUNT(*) > 0 +1 +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log WHERE frag LIKE '%xyz%'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 1 FROM mysql.wsrep_streaming_log WHERE frag LIKE '%SAVEPOINT `A`%'; +COUNT(*) = 1 +0 +SELECT COUNT(*) = 1 FROM mysql.wsrep_streaming_log WHERE frag LIKE '%ROLLBACK TO `A`%'; +COUNT(*) = 1 +0 +connection node_2; +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log WHERE frag LIKE '%abcdef%'; +COUNT(*) > 0 +1 +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log WHERE frag LIKE '%xyz%'; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 1 FROM mysql.wsrep_streaming_log WHERE frag LIKE '%SAVEPOINT `A`%'; +COUNT(*) = 1 +0 +SELECT COUNT(*) = 1 FROM mysql.wsrep_streaming_log WHERE frag LIKE '%ROLLBACK TO `A`%'; +COUNT(*) = 1 +0 +connection node_1; +ROLLBACK; +connection node_1a; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_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..cb4d48b3600 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-572.result @@ -0,0 +1,37 @@ +connection node_2; +connection node_1; +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; +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; +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 mysql.wsrep_streaming_log; +node_uuid trx_id seqno flags frag +connection node_1a; +INSERT INTO t1 VALUES(15, 'node2'); +connection node_1; +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..3ee69c6c4b3 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-580.result @@ -0,0 +1,13 @@ +connection node_2; +connection node_1; +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..ab5fed59081 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-585.result @@ -0,0 +1,28 @@ +connection node_2; +connection node_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); +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; +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; +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..7afca229251 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-597.result @@ -0,0 +1,21 @@ +connection node_2; +connection node_1; +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; +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..33789f82add --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-620.result @@ -0,0 +1,18 @@ +connection node_2; +connection node_1; +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; +COUNT(*) = 2 +0 +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..f3500b7ac2b --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-623.result @@ -0,0 +1,29 @@ +connection node_2; +connection node_1; +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; +COUNT(*) = 0 +1 +connection node_1; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..891cf4af5a9 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-627.result @@ -0,0 +1,26 @@ +connection node_2; +connection node_1; +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; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +INSERT INTO t1 VALUES (2); +ERROR 42S02: Table 'test.t1' doesn't exist +connection node_1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..df842049332 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-845.result @@ -0,0 +1,21 @@ +connection node_2; +connection node_1; +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; +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..52aa4c78745 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-851.result @@ -0,0 +1,30 @@ +connection node_2; +connection node_1; +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 mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +connection node_2; +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +connection node_1; +START TRANSACTION; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) > 0 FROM t1; +COUNT(*) > 0 +1 +connection node_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..9521a86d621 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-867.result @@ -0,0 +1,4 @@ +connection node_2; +connection node_1; +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..617377de15a --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-889.result @@ -0,0 +1,25 @@ +connection node_2; +connection node_1; +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; +COUNT(*) = 1 +1 +connection node_2; +SELECT COUNT(*) = 1; +COUNT(*) = 1 +1 +CALL mtr.add_suppression("Could not execute Delete_rows event on table"); +CALL mtr.add_suppression("Can't find record in 't1'"); +SET GLOBAL wsrep_ignore_apply_errors = 7; +connection node_1; +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..caa2d2c4138 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/GCF-900.result @@ -0,0 +1,21 @@ +connection node_2; +connection node_1; +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; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +connection node_1a; +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..1d04b6f9cee --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera-features#56.result @@ -0,0 +1,32 @@ +connection node_2; +connection node_1; +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; +SET GLOBAL wsrep_slave_threads = 4; +SET SESSION wsrep_trx_fragment_size = 1; +connection node_1; +INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;; +connection node_1a; +INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;; +connection node_2; +INSERT INTO t1 (f2) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;; +connection node_1; +connection node_1a; +connection node_2; +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 +0 +connection default; +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..bf92a48b242 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_bf_abort.result @@ -0,0 +1,555 @@ +connection node_2; +connection node_1; +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET SESSION wsrep_sync_wait = 0; +galera_sr_bf_abort_at_commit = 0 +after_replicate_sync +connection node_1; +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 +connection node_1a; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (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,after_replicate_sync'; +connection node_1; +INSERT INTO t1 VALUES (3); +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=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync'; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +ROLLBACK; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +connection node_1; +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +connection node_2; +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +connection node_1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_1; +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +local_monitor_master_enter_sync +connection node_1; +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 +connection node_1a; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (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,local_monitor_master_enter_sync'; +connection node_1; +INSERT INTO t1 VALUES (3); +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=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=local_monitor_master_enter_sync'; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +ROLLBACK; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +connection node_1; +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +connection node_2; +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +connection node_1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_1; +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +apply_monitor_master_enter_sync +connection node_1; +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 +connection node_1a; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (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,apply_monitor_master_enter_sync'; +connection node_1; +INSERT INTO t1 VALUES (3); +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=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_master_enter_sync'; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +ROLLBACK; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +connection node_1; +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +connection node_2; +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +connection node_1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_1; +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +commit_monitor_master_enter_sync +connection node_1; +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 +connection node_1a; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (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; +INSERT INTO t1 VALUES (3); +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=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync'; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +ROLLBACK; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +connection node_1; +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +connection node_2; +SELECT * FROM t1; +f1 +2 +SELECT COUNT(*) = 1 FROM t1 WHERE f1 = 2; +COUNT(*) = 1 +1 +connection node_1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_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 +connection node_1; +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 +connection node_1a; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (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,after_replicate_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=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=after_replicate_sync'; +connection node_1; +ROLLBACK; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +connection node_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 +connection node_2; +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 +connection node_1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_1; +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +local_monitor_master_enter_sync +connection node_1; +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 +connection node_1a; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (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,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 = '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'; +connection node_1; +ROLLBACK; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +connection node_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 +connection node_2; +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 +connection node_1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_1; +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +apply_monitor_master_enter_sync +connection node_1; +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 +connection node_1a; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (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,apply_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=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_master_enter_sync'; +connection node_1; +ROLLBACK; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +connection node_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 +connection node_2; +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 +connection node_1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_1; +SET AUTOCOMMIT=ON; +SET SESSION wsrep_trx_fragment_size = 0; +DELETE FROM t1; +DROP TABLE t1; +commit_monitor_master_enter_sync +connection node_1; +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 +connection node_1a; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +SET AUTOCOMMIT=ON; +INSERT INTO t1 VALUES (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=abort_trx_end'; +SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync'; +connection node_1; +ROLLBACK; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end'; +connection node_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 +connection node_2; +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 +connection node_1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_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..db25f54a611 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_blob.result @@ -0,0 +1,23 @@ +connection node_2; +connection node_1; +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; +connection node_1; +INSERT INTO t1 VALUES (REPEAT('x', 65535)); +connection node_2; +wsrep_last_committed_delta +1 +connection node_1; +COMMIT; +connection node_2; +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..79bc29200f9 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_cc_master.result @@ -0,0 +1,65 @@ +connection node_2; +connection node_1; +connection node_1; +connection node_2; +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); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +connection node_1; +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_2a; +SET SESSION wsrep_sync_wait=0; +SET GLOBAL wsrep_cluster_address = ''; +SET SESSION wsrep_sync_wait = DEFAULT; +connection node_2; +INSERT INTO t1 VALUES (6); +ERROR HY000: Lost connection to MySQL server during query +connection node_1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2a; +connection node_1; +connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_2b; +SELECT * FROM mysql.wsrep_streaming_log; +node_uuid trx_id seqno flags frag +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_1; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +DROP TABLE t1; +connection node_2b; +CALL mtr.add_suppression("WSREP: Failed to replicate rollback fragment for"); +disconnect node_2; +connect node_2, 127.0.0.1, root, , test, $NODE_MYPORT_2; 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..671745c8686 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_cc_slave.result @@ -0,0 +1,59 @@ +connection node_2; +connection node_1; +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +connection node_2; +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +connection node_2; +SET GLOBAL wsrep_cluster_address = ''; +SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_sync_wait = default; +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); +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +connection node_2; +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +DROP TABLE t1; +CALL mtr.add_suppression("points to own listening address, blacklisting"); 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..75acba366c2 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_concurrent.result @@ -0,0 +1,36 @@ +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; +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; +COUNT(*) = 5 +1 +SELECT COUNT(*) = 5 FROM t2; +COUNT(*) = 5 +1 +connection node_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..a45bffeaa81 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_conflict.result @@ -0,0 +1,21 @@ +connection node_2; +connection node_1; +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; +INSERT INTO t1 VALUES(1);; +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_1; +COMMIT; +connection node_2; +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..5de1ac2422c --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit.result @@ -0,0 +1,31 @@ +connection node_2; +connection node_1; +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; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +connection node_1; +COMMIT; +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; 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..2ee3d4c714c --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_conflict_on_commit2.result @@ -0,0 +1,28 @@ +connection node_2; +connection node_1; +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; +INSERT INTO t1 VALUES (5);; +connection node_1; +COMMIT; +connection node_2; +ERROR 23000: Duplicate entry '5' for key 'PRIMARY' +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; 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..92bf007e21b --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_conflict_with_rollback_master.result @@ -0,0 +1,29 @@ +connection node_2; +connection node_1; +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; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +connection node_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..cf9c7771bed --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_ddl_master.result @@ -0,0 +1,48 @@ +connection node_2; +connection node_1; +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 TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +connection node_1; +INSERT INTO t1 VALUES (6); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 6 FROM t1; +COUNT(*) = 6 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..fcd6cfa4a6e --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_ddl_schema.result @@ -0,0 +1,23 @@ +connection node_2; +connection node_1; +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; +DROP SCHEMA test; +SELECT COUNT(*) = 0 FROM test.t1; +ERROR 42S02: Table 'test.t1' doesn't exist +connection node_1; +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..58663caf134 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_ddl_slave.result @@ -0,0 +1,50 @@ +connection node_2; +connection node_1; +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; +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +ALTER TABLE t1 DROP COLUMN f2; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_1; +INSERT INTO t1 VALUES (6, 6); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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); +connection node_2; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +connection node_1; +COMMIT; +connection node_2; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..0f23ade58c1 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_ddl_unrelated.result @@ -0,0 +1,42 @@ +connection node_2; +connection node_1; +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; +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +ALTER TABLE t2 DROP COLUMN f2; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +connection node_1; +INSERT INTO t1 VALUES (6, 6); +connection node_2; +connection node_1; +COMMIT; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 6 FROM t1; +COUNT(*) = 6 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..b23b934da33 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_dupkey_error.result @@ -0,0 +1,46 @@ +connection node_2; +connection node_1; +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; +connection node_1; +INSERT INTO t1 VALUES (REPEAT('c', 512)); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +connection node_1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +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; +COUNT(*) = 6 +1 +connection node_2; +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..1d12533cc1d --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_fk_conflict.result @@ -0,0 +1,39 @@ +connection node_2; +connection node_1; +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); +connection node_1; +SET AUTOCOMMIT=OFF; +SET SESSION wsrep_trx_fragment_size = 1; +START TRANSACTION; +UPDATE grandparent SET id = 5 WHERE id = 1; +connection node_2; +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 +connection node_1; +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..be631d1d916 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_gtid.result @@ -0,0 +1,57 @@ +connection node_2; +connection node_1; +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; +COUNT(*) = 1 +1 +SET SESSION wsrep_trx_fragment_size=1; +UPDATE t1 SET f1 = 2; +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; +COUNT(*) = 1 +1 +SHOW BINLOG EVENTS IN 'mysqld-bin.000002' FROM 256; +Log_name Pos Event_type Server_id End_log_pos Info +mysqld-bin.000002 <Pos> Gtid_list 1 <End_log_pos> [] +mysqld-bin.000002 <Pos> Binlog_checkpoint 1 <End_log_pos> mysqld-bin.000001 +mysqld-bin.000002 <Pos> Binlog_checkpoint 1 <End_log_pos> mysqld-bin.000002 +mysqld-bin.000002 <Pos> Gtid 1 <End_log_pos> GTID 0-1-1 +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> BEGIN GTID 0-1-2 +mysqld-bin.000002 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (1) +mysqld-bin.000002 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1) +mysqld-bin.000002 <Pos> Write_rows_v1 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 2 <End_log_pos> BEGIN GTID 0-2-3 +mysqld-bin.000002 <Pos> Annotate_rows 2 <End_log_pos> UPDATE t1 SET f1 = 2 +mysqld-bin.000002 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t1) +mysqld-bin.000002 <Pos> Update_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000002 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */ +connection node_2; +SELECT 1 FROM DUAL; +1 +1 +SHOW BINLOG EVENTS IN 'mysqld-bin.000003' FROM 256; +Log_name Pos Event_type Server_id End_log_pos Info +mysqld-bin.000003 <Pos> Gtid_list 2 <End_log_pos> [] +mysqld-bin.000003 <Pos> Binlog_checkpoint 2 <End_log_pos> mysqld-bin.000003 +mysqld-bin.000003 <Pos> Gtid 1 <End_log_pos> GTID 0-1-1 +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> BEGIN GTID 0-1-2 +mysqld-bin.000003 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (1) +mysqld-bin.000003 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1) +mysqld-bin.000003 <Pos> Write_rows_v1 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> BEGIN GTID 0-2-3 +mysqld-bin.000003 <Pos> Annotate_rows 2 <End_log_pos> UPDATE t1 SET f1 = 2 +mysqld-bin.000003 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t1) +mysqld-bin.000003 <Pos> Update_rows_v1 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..0302290123d --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_insert_select.result @@ -0,0 +1,18 @@ +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); +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; +connection node_2; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +connection node_1; +COMMIT; +connection node_2; +connection node_1; +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..a78926a9794 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_all_nobootstrap.result @@ -0,0 +1,29 @@ +connection node_2; +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; +Killing server ... +connection node_1; +Killing server ... +connection node_1; +connection node_2; +connection node_1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..7525cd6d4b7 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_all_norecovery.result @@ -0,0 +1,30 @@ +connection node_2; +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; +Killing server ... +connection node_1; +Killing server ... +connection node_1; +connection node_2; +connection node_1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..7525cd6d4b7 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_all_pcrecovery.result @@ -0,0 +1,30 @@ +connection node_2; +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; +Killing server ... +connection node_1; +Killing server ... +connection node_1; +connection node_2; +connection node_1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..96a85bc038b --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_connection.result @@ -0,0 +1,32 @@ +connection node_2; +connection node_1; +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); +connection node_2; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +connection node_1; +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connection 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; +COUNT(*) = 5 +1 +connection node_1a; +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..59942e717e7 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_query.result @@ -0,0 +1,31 @@ +connection node_2; +connection node_1; +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;; +connection node_2; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +connection node_1; +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +Killing query ... +connection node_1; +ERROR 70100: Query execution was interrupted +connection node_2; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +INSERT INTO t1 SELECT 1 FROM ten AS t1, ten AS t2, ten AS t3; +SELECT COUNT(*) = 1000 FROM t1; +COUNT(*) = 1000 +1 +connection node_1a; +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..b4e84b1b72a --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_kill_slave.result @@ -0,0 +1,53 @@ +connection node_2; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +connection node_2; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +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; +Killing server ... +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; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 15 FROM t1; +COUNT(*) = 15 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_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..bf111f5cee4 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_large_fragment.result @@ -0,0 +1,33 @@ +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 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 mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) > 50000 FROM t1; +COUNT(*) > 50000 +1 +connection node_1; +ROLLBACK; +connection node_2; +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 mysql.wsrep_streaming_log; +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..a474a7e3ae8 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_load_data.result @@ -0,0 +1,13 @@ +connection node_2; +connection node_1; +SET SESSION wsrep_trx_fragment_size = 512; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +connection node_2; +connection node_1; +connection node_2; +SELECT COUNT(*) = 20000 FROM t1; +COUNT(*) = 20000 +1 +wsrep_last_committed_diff +0 +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..cb8e84383bc --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_log_bin.result @@ -0,0 +1,124 @@ +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; +connection node_2; +connection node_1; +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; +SET GLOBAL wsrep_on=OFF; +RESET MASTER; +SET GLOBAL wsrep_on=ON; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t2 VALUES (1); +connection node_2; +SET GLOBAL wsrep_on=OFF; +RESET MASTER; +SET GLOBAL wsrep_on=ON; +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; +COUNT(*) = 2 +1 +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> BEGIN GTID 0-1-1 +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> 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> Gtid 1 <End_log_pos> BEGIN GTID 0-1-2 +mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t2 VALUES (1) +mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t2) +mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t2 VALUES (2) +mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t2) +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 2 <End_log_pos> BEGIN GTID 0-2-3 +mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t3 VALUES (1) +mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t3) +mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t3 VALUES (2) +mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t3) +mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000001 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */ +mysqld-bin.000001 <Pos> Gtid 2 <End_log_pos> BEGIN GTID 0-2-4 +mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t4 VALUES (1) +mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t4) +mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t4 VALUES (2) +mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t4) +mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000001 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */ +connection node_2; +SELECT COUNT(*) = 2 FROM t4; +COUNT(*) = 2 +1 +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 2 <End_log_pos> [] +mysqld-bin.000001 <Pos> Binlog_checkpoint 2 <End_log_pos> mysqld-bin.000001 +mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> BEGIN GTID 0-1-1 +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> 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> Gtid 1 <End_log_pos> BEGIN GTID 0-1-2 +mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t2 VALUES (1) +mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t2) +mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t2 VALUES (2) +mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t2) +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 2 <End_log_pos> BEGIN GTID 0-2-3 +mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t3 VALUES (1) +mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t3) +mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t3 VALUES (2) +mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t3) +mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000001 <Pos> Xid 2 <End_log_pos> COMMIT /* xid=### */ +mysqld-bin.000001 <Pos> Gtid 2 <End_log_pos> BEGIN GTID 0-2-4 +mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t4 VALUES (1) +mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t4) +mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000001 <Pos> Annotate_rows 2 <End_log_pos> INSERT INTO t4 VALUES (2) +mysqld-bin.000001 <Pos> Table_map 2 <End_log_pos> table_id: ### (test.t4) +mysqld-bin.000001 <Pos> Write_rows_v1 2 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.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..8c89d100260 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_many_fragments.result @@ -0,0 +1,33 @@ +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 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; +connection node_2; +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 10000 FROM t1; +COUNT(*) = 10000 +1 +connection node_1; +ROLLBACK; +connection node_2; +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 mysql.wsrep_streaming_log; +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..97818f072e1 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_myisam.result @@ -0,0 +1,16 @@ +connection node_2; +connection node_1; +connection node_1; +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)); +connection node_2; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT LENGTH(f1) = 65535 FROM t1; +LENGTH(f1) = 65535 +1 +DROP TABLE t1; +connection node_1; 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..f1b60c7f76a --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_mysqldump_sst.result @@ -0,0 +1,58 @@ +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"); +connection node_1; +CREATE USER 'sst'; +GRANT ALL PRIVILEGES ON *.* TO 'sst'; +SET GLOBAL wsrep_sst_auth = 'sst:'; +connection node_2; +SET GLOBAL wsrep_sst_method = 'mysqldump'; +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 INTO t1 (f2) SELECT REPEAT('x', 255) FROM ten AS a1, ten AS a2, ten AS a3; +UPDATE t1 SET f2 = REPEAT('y', 255); +connection node_2; +connection node_2; +Shutting down server ... +connection node_1; +connection node_2; +Starting server ... +connection node_1; +connection node_2; +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +connection node_1; +UPDATE t1 SET f2 = REPEAT('z', 255); +COMMIT; +connection node_2; +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; +connection node_1; +SET SESSION wsrep_trx_fragment_size=0; +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; +connection node_2; +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("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_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..e2194e08cb8 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_parallel_apply.result @@ -0,0 +1,37 @@ +connection node_2; +connection node_1; +connection node_2; +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); +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); +INSERT INTO t1 (f2) VALUES (2);; +connection node_2; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +connection node_1; +COMMIT; +connection node_1a; +ROLLBACK; +connection node_2; +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SELECT COUNT(*) = 5 FROM t1; +COUNT(*) = 5 +1 +connection node_1; +DROP TABLE t1; +connection node_2; 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..4b275c6e0b6 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_rollback.result @@ -0,0 +1,42 @@ +connection node_2; +connection node_1; +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; +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; +connection node_1; +ROLLBACK; +connection node_2; +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; +connection node_1; +COMMIT; +connection node_2; +connection node_1; +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..054f7cf2eae --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_rollback_retry.result @@ -0,0 +1,33 @@ +connection node_2; +connection node_1; +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); +connection node_2; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +connection node_1; +ROLLBACK; +connection 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; +COUNT(*) = 5 +1 +connection node_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..f2efa20f0d3 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_rollback_savepoint.result @@ -0,0 +1,42 @@ +connection node_2; +connection node_1; +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; +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; +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'; +COUNT(*) = 5 +1 +SELECT COUNT(*) = 0 FROM t1 WHERE f2 = 'b'; +COUNT(*) = 0 +0 +SELECT COUNT(*) = 5 FROM t1 WHERE f2 = 'c'; +COUNT(*) = 5 +1 +connection node_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..eb493f66ed6 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_shutdown_master.result @@ -0,0 +1,31 @@ +connection node_2; +connection node_1; +connection node_1; +connection node_2; +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; +connection node_2; +connection node_1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +INSERT INTO t1 VALUES (1),(2),(3); +connection node_1; +SELECT COUNT(*) = 3 FROM t1; +COUNT(*) = 3 +1 +DROP TABLE t1; +connection node_2; +CALL mtr.add_suppression("WSREP: Failed to replicate rollback fragment 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..568452b10b0 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_shutdown_slave.result @@ -0,0 +1,43 @@ +connection node_2; +connection node_1; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE = InnoDB; +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; +connection node_1; +connection node_1a; +INSERT INTO t1 VALUES (14),(15),(16); +COMMIT; +connection node_2; +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; +COUNT(*) > 0 +1 +SELECT COUNT(*) = 6 FROM t1 WHERE f1 IN (11,12,13,14,15,16); +COUNT(*) = 6 +1 +connection node_1b; +INSERT INTO t1 VALUES (24),(25),(26); +COMMIT; +connection node_2; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 12 FROM t1; +COUNT(*) = 12 +1 +connection node_1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..875f2df5214 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_small_gcache.result @@ -0,0 +1,15 @@ +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); +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; +COUNT(*) = 10000 +1 +connection node_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..5806ab5558d --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_transaction_replay.result @@ -0,0 +1,121 @@ +connection node_2; +connection node_1; +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET SESSION wsrep_sync_wait = 0; +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; +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 +connection node_1a; +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,local_monitor_master_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 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'; +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 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +wsrep_local_replays +1 +connection node_2; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +DELETE FROM t1; +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 = '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 +connection node_1a; +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,local_monitor_master_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 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'; +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 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +wsrep_local_replays +1 +connection node_2; +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 mysql.wsrep_streaming_log; +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..4e3bd52483e --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_unit_statements.result @@ -0,0 +1,54 @@ +connection node_2; +connection node_1; +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); +connection node_2; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +SELECT COUNT(*) FROM mysql.wsrep_streaming_log; +COUNT(*) +0 +connection node_1; +INSERT INTO t1 VALUES (2); +connection node_2; +SELECT COUNT(*) FROM t1; +COUNT(*) +2 +SELECT COUNT(*) FROM mysql.wsrep_streaming_log; +COUNT(*) +1 +connection node_1; +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); +connection node_2; +SELECT COUNT(*) FROM t1; +COUNT(*) +5 +SELECT COUNT(*) FROM mysql.wsrep_streaming_log; +COUNT(*) +2 +connection node_1; +COMMIT; +SELECT COUNT(*) FROM t1; +COUNT(*) +5 +SELECT COUNT(*) FROM mysql.wsrep_streaming_log; +COUNT(*) +0 +connection node_2; +SELECT COUNT(*) FROM t1; +COUNT(*) +5 +SELECT COUNT(*) FROM mysql.wsrep_streaming_log; +COUNT(*) +0 +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..ab090e5c2a7 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_v1_row_events.result @@ -0,0 +1,20 @@ +connection node_2; +connection node_1; +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; +COUNT(*) = 1 +1 +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; +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..b7bdd94dd68 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_ws_size.result @@ -0,0 +1,36 @@ +connection node_2; +connection node_1; +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); +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; +connection node_2; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +connection node_1; +COMMIT; +connection node_2; +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +SELECT COUNT(*) = 100 FROM t1; +COUNT(*) = 100 +1 +DROP TABLE t1; +DROP TABLE ten; +connection node_1; +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..6bd8b6b8212 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_sr_ws_size2.result @@ -0,0 +1,34 @@ +connection node_2; +connection node_1; +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); +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 +connection node_2; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +connection node_2; +SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +connection node_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..852208437e5 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/galera_var_ignore_apply_errors_sr.result @@ -0,0 +1,29 @@ +connection node_2; +connection node_1; +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; +COUNT(*) = 1 +1 +connection node_2; +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"); +CALL mtr.add_suppression("Can't find record in 't1'"); 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..623bef4c3c4 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep#215.result @@ -0,0 +1,137 @@ +connection node_2; +connection node_1; +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +SET SESSION wsrep_trx_fragment_size = 2; +SET SESSION wsrep_trx_fragment_unit = 'statements'; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +connection node_1a; +SET GLOBAL DEBUG_DBUG = 'd,sync.wsrep_apply_cb'; +SET SESSION wsrep_sync_wait = 0; +connection node_2; +INSERT INTO t1 VALUES (1); +connection node_1a; +SET SESSION debug_sync = "now WAIT_FOR sync.wsrep_apply_cb_reached"; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +connection node_1; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +INSERT INTO t1 VALUES (1);; +connection node_1a; +connection node_1a; +SET GLOBAL DEBUG_DBUG = ''; +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +COMMIT; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_1a; +SET DEBUG_SYNC = 'RESET'; +connection node_1; +TRUNCATE TABLE t1; +SET SESSION wsrep_trx_fragment_size = 10; +SET SESSION wsrep_trx_fragment_unit = 'bytes'; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +connection node_1a; +SET GLOBAL DEBUG_DBUG = 'd,sync.wsrep_apply_cb'; +SET SESSION wsrep_sync_wait = 0; +connection node_2; +INSERT INTO t1 VALUES (1); +connection node_1a; +SET SESSION debug_sync = "now WAIT_FOR sync.wsrep_apply_cb_reached"; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +connection node_1; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +INSERT INTO t1 VALUES (1); +connection node_1a; +SET GLOBAL DEBUG_DBUG = ''; +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +ROLLBACK; +SELECT * FROM t1; +f1 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT * FROM t1; +f1 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_1a; +SET DEBUG_SYNC = 'RESET'; +connection node_1; +TRUNCATE TABLE t1; +SET SESSION wsrep_trx_fragment_size = 200; +SET SESSION wsrep_trx_fragment_unit = 'bytes'; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +SET AUTOCOMMIT=OFF; +START TRANSACTION; +connection node_1a; +SET GLOBAL DEBUG_DBUG = 'd,sync.wsrep_apply_cb'; +SET SESSION wsrep_sync_wait = 0; +connection node_2; +INSERT INTO t1 VALUES (1); +connection node_1a; +SET SESSION debug_sync = "now WAIT_FOR sync.wsrep_apply_cb_reached"; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +connection node_1; +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +connection node_1a; +SET GLOBAL DEBUG_DBUG = ''; +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +COMMIT; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_1a; +DROP TABLE t1; +SET DEBUG_SYNC = 'RESET'; +connection node_2; +CALL mtr.add_suppression("WSREP: Could not find applier context for"); 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..25bc2e11a3e --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#136.result @@ -0,0 +1,65 @@ +connection node_2; +connection node_1; +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; +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; +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) 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),(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> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (1),(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> Gtid 1 <End_log_pos> BEGIN GTID 0-1-3 +mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (3),(4) +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=### */ +connection node_2; +SELECT COUNT(*) = 4 FROM t1; +COUNT(*) = 4 +1 +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 2 <End_log_pos> [] +mysqld-bin.000001 <Pos> Binlog_checkpoint 2 <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) 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),(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> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (1),(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> Gtid 1 <End_log_pos> BEGIN GTID 0-1-3 +mysqld-bin.000001 <Pos> Annotate_rows 1 <End_log_pos> INSERT INTO t1 VALUES (3),(4) +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=### */ +connection node_1; +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..fc9afd6e1e0 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#138.result @@ -0,0 +1,24 @@ +connection node_2; +connection node_1; +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 mysql.wsrep_streaming_log; +flags +1 +0 +connection node_1; +ROLLBACK; +INSERT INTO t1 VALUES (3),(4); +connection node_2; +SELECT flags FROM mysql.wsrep_streaming_log; +flags +1 +0 +connection node_1; +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..b09c7d4047a --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#14.result @@ -0,0 +1,12 @@ +connection node_2; +connection node_1; +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; 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..a85c0f302d0 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#148.result @@ -0,0 +1,42 @@ +connection node_2; +connection node_1; +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'; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +connection node_1; +SET SESSION wsrep_trx_fragment_size = 1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1), (2), (3), (4), (5); +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connection node_1a; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 VALUES (1), (2), (3), (4), (5);; +connection node_1; +INSERT INTO t1 SELECT * FROM t2;; +connection node_1a; +INSERT INTO t1 VALUES (6), (7), (8), (9), (10); +COMMIT; +connection node_1; +Got one of the listed errors +connection node_2; +SET GLOBAL wsrep_slave_threads = 1; +SET GLOBAL DEBUG = ''; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +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..610019e2b48 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#15.result @@ -0,0 +1,11 @@ +connection node_2; +connection node_1; +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/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#22.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#22.result new file mode 100644 index 00000000000..0053619187c --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#22.result @@ -0,0 +1,35 @@ +connection node_2; +connection node_1; +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; +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; +connection node_1; +ROLLBACK TO SAVEPOINT s1; +INSERT INTO t1 VALUES (21, 'c'); +COMMIT; +connection node_1; +SELECT COUNT(*) = 6 FROM t1; +COUNT(*) = 6 +1 +connection node_2; +SELECT COUNT(*) = 6 FROM t1; +COUNT(*) = 6 +0 +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..4cbcd49dd24 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#27.result @@ -0,0 +1,23 @@ +connection node_2; +connection node_1; +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; +SET SESSION wsrep_sync_wait = 0; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +connection node_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..ca749a45e9a --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#32.result @@ -0,0 +1,27 @@ +connection node_2; +connection node_1; +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; +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; +connection node_1; +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..41657d7340a --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#35.result @@ -0,0 +1,41 @@ +connection node_2; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SET SESSION wsrep_sync_wait = 0; +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; +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_2a; +SET SESSION debug_sync = "now WAIT_FOR sync.wsrep_apply_cb_reached"; +connection node_2; +SET SESSION wsrep_sync_wait = 0; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +INSERT INTO t1 VALUES (1);; +connection node_1; +COMMIT; +connection node_2a; +SET GLOBAL debug = ''; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; +connection node_2; +Got one of the listed errors +ROLLBACK; +DROP TABLE t1; +connection node_2a; +SET DEBUG_SYNC = "RESET"; 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..56905c03e10 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#8.result @@ -0,0 +1,39 @@ +connection node_2; +connection node_1; +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); +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/%'; +COUNT(*) = 13 +1 +connection node_1; +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'); +COUNT(f2) = 10000 +1 +UPDATE t1 SET f2 = 'abcdefjhk'; +connection node_1; +SELECT COUNT(f2) = 10000 FROM t1 WHERE MATCH(f2) AGAINST ('abcdefjhk'); +COUNT(f2) = 10000 +1 +connection node_2; +DROP TABLE t1; +connection node_1; +CREATE TABLE t1 (f1 VARCHAR(100), FULLTEXT (f1)) ENGINE=InnoDB; +connection node_2; +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'); +COUNT(f1) = 1000 +1 +UPDATE t1 SET f1 = 'abcdefjhk'; +connection node_2; +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..990ea47f8bc --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#9.result @@ -0,0 +1,20 @@ +connection node_2; +connection node_1; +connection node_1; +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; +Killing server ... +connection node_1; +ALTER TABLE t1 ADD COLUMN f2 INTEGER; +connection node_2; +connection node_2a; +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 +connection node_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..17f71213767 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#93.result @@ -0,0 +1,18 @@ +connection node_2; +connection node_1; +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 mysql.wsrep_streaming_log; +COUNT(*) = 0 +1 +connection node_2; +SELECT COUNT(*) = 0 from mysql.wsrep_streaming_log; +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..dbe91aad9fd --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-features#96.result @@ -0,0 +1,33 @@ +connection node_2; +connection node_1; +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); +INSERT INTO t1 VALUES (2),(1); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +INSERT INTO t2 VALUES ('abc'); +connection node_2; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 1 FROM t2; +COUNT(*) = 1 +1 +connection node_1; +ROLLBACK; +connection node_2; +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +SELECT COUNT(*) = 0 FROM t1; +COUNT(*) = 0 +1 +SELECT COUNT(*) = 0 FROM t2; +COUNT(*) = 0 +1 +connection node_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..1db4ed15c41 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-1051.test @@ -0,0 +1,51 @@ +# +# 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 mysql.wsrep_streaming_log; + +--connection node_2 +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +# +# 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 mysql.wsrep_streaming_log; + +--connection node_2 +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + + +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..f71be65708e --- /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 mysql.wsrep_streaming_log: 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..4a652284e59 --- /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 mysql.wsrep_streaming_log; + +ALTER TABLE t1 DROP COLUMN f2; + +# SR applied before the DDL is no longer visible +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +--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 mysql.wsrep_streaming_log; + +# 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 mysql.wsrep_streaming_log; + +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..aca0b9f7907 --- /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 mysql.wsrep_streaming_log WHERE frag LIKE '%abcdef%'; +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log WHERE frag LIKE '%xyz%'; +SELECT COUNT(*) = 1 FROM mysql.wsrep_streaming_log WHERE frag LIKE '%SAVEPOINT `A`%'; + +--connection node_1 +ROLLBACK TO SAVEPOINT A; + +--connection node_1a +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log WHERE frag LIKE '%abcdef%'; +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log WHERE frag LIKE '%xyz%'; +SELECT COUNT(*) = 1 FROM mysql.wsrep_streaming_log WHERE frag LIKE '%SAVEPOINT `A`%'; +SELECT COUNT(*) = 1 FROM mysql.wsrep_streaming_log WHERE frag LIKE '%ROLLBACK TO `A`%'; + +--connection node_2 +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log WHERE frag LIKE '%abcdef%'; +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log WHERE frag LIKE '%xyz%'; +SELECT COUNT(*) = 1 FROM mysql.wsrep_streaming_log WHERE frag LIKE '%SAVEPOINT `A`%'; +SELECT COUNT(*) = 1 FROM mysql.wsrep_streaming_log WHERE frag LIKE '%ROLLBACK TO `A`%'; + +--connection node_1 +ROLLBACK; + +--connection node_1a +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +--connection node_2 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +--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..abefb9b08f6 --- /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 mysql.wsrep_streaming_log; + +--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..39a237fda57 --- /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 mysql.wsrep_streaming_log` +--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..ceb7da60df6 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-585.test @@ -0,0 +1,44 @@ +# +# 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); +# 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 (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..6784989bde9 --- /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 mysql.wsrep_streaming_log; + +--connection node_2 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +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..86637ad8e7f --- /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 mysql.wsrep_streaming_log; + +--connection node_2 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +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..316317c6a10 --- /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 mysql.wsrep_streaming_log; + +--connection node_1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +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..28d5302a422 --- /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 mysql.wsrep_streaming_log; +--connection node_2 +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; + +--connection node_1 +START TRANSACTION; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +--connection node_2 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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..54476a860b7 --- /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 = 62 + +--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..e785b282019 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/GCF-889.test @@ -0,0 +1,29 @@ +--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"); +CALL mtr.add_suppression("Can't find record in 't1'"); +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..94f328bf31b --- /dev/null +++ b/mysql-test/suite/galera_sr/t/disabled.def @@ -0,0 +1,3 @@ +mysql-wsrep-features#29 : binlog_format=STATEMENT not supported with SR +GCF-574 : CTAS is not supported together with SR +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..cd9884cee81 --- /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 mysql.wsrep_streaming_log; +--connection node_2 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +# 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..a2db6a8bad2 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_bf_abort.test @@ -0,0 +1,50 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc +--source include/galera_have_debug_sync.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..8ae8c204f60 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_cc_master.test @@ -0,0 +1,98 @@ +--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. +# + +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--source ../galera/include/auto_increment_offset_save.inc + +--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 mysql.wsrep_streaming_log; + +--connection node_1 +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; + +# +# 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 +SET SESSION wsrep_sync_wait=0; +--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address` +SET GLOBAL wsrep_cluster_address = ''; + +--let $wait_condition = SELECT VARIABLE_VALUE = 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +SET SESSION wsrep_sync_wait = DEFAULT; + +--connection node_2 +--error 2013 # CR_SERVER_LOST +INSERT INTO t1 VALUES (6); + +--connection node_1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +# Restore cluster + +--connection node_2a +--disable_query_log +--eval SET GLOBAL wsrep_cluster_address='$wsrep_cluster_address_orig' +--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 + + +--connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2b +--source include/galera_wait_ready.inc +SELECT * FROM mysql.wsrep_streaming_log; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +# 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 mysql.wsrep_streaming_log; + +--connection node_1 +SELECT COUNT(*) = 5 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +DROP TABLE t1; + +--connection node_2b +CALL mtr.add_suppression("WSREP: Failed to replicate rollback fragment for"); + +--disconnect node_2 +--connect node_2, 127.0.0.1, root, , test, $NODE_MYPORT_2 +# Restore original auto_increment_offset values. +--source ../galera/include/auto_increment_offset_restore.inc 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..8c790ac7cd2 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_cc_slave.test @@ -0,0 +1,97 @@ +--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 mysql.wsrep_streaming_log; + +--connection node_1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; + +--connection node_2 +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; + +# +# 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 = ''; + +# Wait until the node_2 disconnects from the cluster +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT VARIABLE_VALUE = 'Disconnected' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status' +--source include/wait_condition.inc +SET SESSION wsrep_sync_wait = default; + +--connection node_1 + +# Wait until the node_1 sees the cluster configuration change +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +# 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 mysql.wsrep_streaming_log; + +# Restore cluster + +--connection node_2 +--disable_query_log +--eval SET GLOBAL wsrep_cluster_address='$wsrep_cluster_address_orig'; +--enable_query_log +--source include/galera_wait_ready.inc + +# Confirm that the SR table still contains entries from ongoing transaction +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; + +# 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 mysql.wsrep_streaming_log; + +# 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 mysql.wsrep_streaming_log; + +DROP TABLE t1; + +CALL mtr.add_suppression("points to own listening address, blacklisting"); 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..dd133c2d12e --- /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 'wsrep applier 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..7da7f55ba15 --- /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 mysql.wsrep_streaming_log; + +--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 mysql.wsrep_streaming_log; + +# 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 mysql.wsrep_streaming_log; + +--connection node_2 +SELECT COUNT(*) = 6 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +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..4a652284e59 --- /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 mysql.wsrep_streaming_log; + +ALTER TABLE t1 DROP COLUMN f2; + +# SR applied before the DDL is no longer visible +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +--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 mysql.wsrep_streaming_log; + +# 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 mysql.wsrep_streaming_log; + +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..77b6e64641d --- /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 mysql.wsrep_streaming_log; + +ALTER TABLE t2 DROP COLUMN f2; + +# SR applied before the DDL is still visible +SELECT COUNT(*) = 5 FROM t1; +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; + +--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 mysql.wsrep_streaming_log; + +--connection node_2 +SELECT COUNT(*) = 6 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +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..a7aca042829 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_dupkey_error.test @@ -0,0 +1,59 @@ +# +# 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 mysql.wsrep_streaming_log; + +--connection node_1 +# Deadlock error instead of dupkey since the transaction is SR and +# statement rollback is not safe. +--error ER_LOCK_DEADLOCK +INSERT INTO t1 VALUES (REPEAT('c', 512)); + +# Confirm that the wsrep_streaming_log table is now empty, as it was a full transaction rollback + +--connection node_1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; +--connection node_2 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +# 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..6623c33c484 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_gtid-master.opt @@ -0,0 +1 @@ + --log-bin --log-slave-updates --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..56464ba6f63 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_gtid.test @@ -0,0 +1,46 @@ +# +# Test basic Galera operation +# + +--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 256; + +--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 256; + +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..8fba27f9a73 --- /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 mysql.wsrep_streaming_log 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 mysql.wsrep_streaming_log; +--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 mysql.wsrep_streaming_log; + +--connection node_2 +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +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..042e3d3ef57 --- /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 mysql.wsrep_streaming_log 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 mysql.wsrep_streaming_log; +--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 mysql.wsrep_streaming_log; + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +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..0ba7cedbd8f --- /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 mysql.wsrep_streaming_log 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 mysql.wsrep_streaming_log; +--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 mysql.wsrep_streaming_log; + +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +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..4c9f2b4d7bc --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_kill_query.test @@ -0,0 +1,48 @@ +--source include/galera_cluster.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 +SELECT COUNT(*) = 0 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +# 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..a76a03e49b9 --- /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 mysql.wsrep_streaming_log; + +--connection node_2 +--sleep 5 +SELECT COUNT(*) = 15 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +--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..63278555723 --- /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 mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +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..7dfa7850c15 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_log_bin.test @@ -0,0 +1,70 @@ +# +# 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 +SET GLOBAL wsrep_on=OFF; +RESET MASTER; +SET GLOBAL wsrep_on=ON; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t2 VALUES (1); + +--connection node_2 +SET GLOBAL wsrep_on=OFF; +RESET MASTER; +SET GLOBAL wsrep_on=ON; +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 'mysqld-bin.000001' FROM 256; + +--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 'mysqld-bin.000001' FROM 256; + +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..9b8dae9d8e3 --- /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; + +--connection node_2 +SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) = 10000 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 mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +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..25ded94e100 --- /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 mysql.wsrep_streaming_log; +--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 mysql.wsrep_streaming_log; +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..3f7407fe536 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_shutdown_master.test @@ -0,0 +1,53 @@ +# +# Shut down master (node #2) while an SR transaction is in progress +# + +--source include/galera_cluster.inc + +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--source ../galera/include/auto_increment_offset_save.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 mysql.wsrep_streaming_log; +--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 mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; + +# 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 replicate rollback fragment for "); + +# Restore original auto_increment_offset values. +--source ../galera/include/auto_increment_offset_restore.inc 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..fa2df242ccc --- /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 mysql.wsrep_streaming_log; +--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 mysql.wsrep_streaming_log; +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 mysql.wsrep_streaming_log; +SELECT COUNT(*) = 12 FROM t1; + +# SR table on master should be empty too +--connection node_1 +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +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..f44d67e5c8c --- /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 mysql.wsrep_streaming_log; + +# +# 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 mysql.wsrep_streaming_log; + +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 mysql.wsrep_streaming_log; + +# +# 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 mysql.wsrep_streaming_log; + +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..0cf05765838 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_sr_unit_statements.test @@ -0,0 +1,54 @@ +# +# 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); + +# Expect noting is replicated yet, so far we have 2 statements +--connection node_2 +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT COUNT(*) FROM t1; +SELECT COUNT(*) FROM mysql.wsrep_streaming_log; + +--connection node_1 +INSERT INTO t1 VALUES (2); + +# Expect 2 rows in t1 and 1 fragment in SR table +--connection node_2 +SELECT COUNT(*) FROM t1; +SELECT COUNT(*) FROM mysql.wsrep_streaming_log; + + --connection node_1 +INSERT INTO t1 VALUES (3); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (5); + +# Expect 5 rows in t1 and 2 fragments in SR table +--connection node_2 +SELECT COUNT(*) FROM t1; +SELECT COUNT(*) FROM mysql.wsrep_streaming_log; + +--connection node_1 +COMMIT; + +# Expect 5 rows in t1 and empty SR table +SELECT COUNT(*) FROM t1; +SELECT COUNT(*) FROM mysql.wsrep_streaming_log; + +--connection node_2 +SELECT COUNT(*) FROM t1; +SELECT COUNT(*) FROM mysql.wsrep_streaming_log; + +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..ea40f58db73 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/galera_var_ignore_apply_errors_sr.test @@ -0,0 +1,38 @@ +# +# 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"); +CALL mtr.add_suppression("Can't find record in 't1'");
\ No newline at end of file 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..81b4a718f68 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep#215.test @@ -0,0 +1,175 @@ +--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 mysql.wsrep_streaming_log; +--let $expected_cert_failures = `SELECT VARIABLE_VALUE + 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'` + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +--connection node_1a +SET GLOBAL DEBUG_DBUG = 'd,sync.wsrep_apply_cb'; +SET SESSION wsrep_sync_wait = 0; + +--connection node_2 +INSERT INTO t1 VALUES (1); + +--connection node_1a +SET SESSION debug_sync = "now WAIT_FOR sync.wsrep_apply_cb_reached"; +SELECT COUNT(*) = 0 FROM t1; + +--connection node_1 +SELECT COUNT(*) = 0 FROM t1; +--send INSERT INTO t1 VALUES (1); + +--connection node_1a +# Wait for the above INSERT to fail certification +--connection node_1a +--let $wait_condition = SELECT VARIABLE_VALUE = $expected_cert_failures FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_cert_failures' +--source include/wait_condition.inc + +SET GLOBAL DEBUG_DBUG = ''; +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; + +--connection node_1 +--error ER_LOCK_DEADLOCK +--reap + +COMMIT; + +SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +--connection node_1a +SET DEBUG_SYNC = 'RESET'; + +# +# 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 mysql.wsrep_streaming_log; +--let $expected_cert_failures = `SELECT VARIABLE_VALUE + 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'` + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +--connection node_1a +SET GLOBAL DEBUG_DBUG = 'd,sync.wsrep_apply_cb'; +SET SESSION wsrep_sync_wait = 0; + +--connection node_2 +INSERT INTO t1 VALUES (1); + +--connection node_1a +SET SESSION debug_sync = "now WAIT_FOR sync.wsrep_apply_cb_reached"; +SELECT COUNT(*) = 0 FROM t1; + +--connection node_1 +SELECT COUNT(*) = 0 FROM t1; +--send INSERT INTO t1 VALUES (1) + +# Wait for the above INSERT to fail certification +--connection node_1a +--let $wait_condition = SELECT VARIABLE_VALUE = $expected_cert_failures FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_cert_failures' +--source include/wait_condition.inc + +SET GLOBAL DEBUG_DBUG = ''; +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; + +--connection node_1 +--error ER_LOCK_DEADLOCK +--reap +ROLLBACK; + +SELECT * FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +--connection node_2 +SELECT * FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +--connection node_1a +SET DEBUG_SYNC = 'RESET'; + +# +# 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 mysql.wsrep_streaming_log; +--let $expected_cert_failures = `SELECT VARIABLE_VALUE + 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'` + +SET AUTOCOMMIT=OFF; +START TRANSACTION; + +--connection node_1a +SET GLOBAL DEBUG_DBUG = 'd,sync.wsrep_apply_cb'; +SET SESSION wsrep_sync_wait = 0; + +--connection node_2 +INSERT INTO t1 VALUES (1); + +--connection node_1a +SET SESSION debug_sync = "now WAIT_FOR sync.wsrep_apply_cb_reached"; +SELECT COUNT(*) = 0 FROM t1; + +--connection node_1 +INSERT INTO t1 VALUES (1); +--send INSERT INTO t1 VALUES (2) + +# Wait for the above INSERT to fail certification +--connection node_1a +--let $wait_condition = SELECT VARIABLE_VALUE = $expected_cert_failures FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_cert_failures' +--source include/wait_condition.inc + +SET GLOBAL DEBUG_DBUG = ''; +SET DEBUG_SYNC='now SIGNAL signal.wsrep_apply_cb'; + +--connection node_1 +--error ER_LOCK_DEADLOCK +--reap +COMMIT; + +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; + +--connection node_1a +DROP TABLE t1; +SET DEBUG_SYNC = 'RESET'; + +--connection node_2 +CALL mtr.add_suppression("WSREP: Could not find applier context for"); 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..06e56d3c9cd --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#136.test @@ -0,0 +1,41 @@ +# SR transactions are not binlogged #136 + +--source include/galera_cluster.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 +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 'mysqld-bin.000001' FROM 256; + +--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 'mysqld-bin.000001' FROM 256; + +--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..3694dc9ad43 --- /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 mysql.wsrep_streaming_log; + +--connection node_1 +ROLLBACK; +INSERT INTO t1 VALUES (3),(4); + +--connection node_2 +SELECT flags FROM mysql.wsrep_streaming_log; + +--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#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..c5cf1dea0ae --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-features#35.test @@ -0,0 +1,48 @@ +--source include/have_debug_sync.inc +--source include/galera_cluster.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; +SET GLOBAL debug = '+d,sync.wsrep_apply_cb'; + +--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_2a +SET SESSION debug_sync = "now WAIT_FOR sync.wsrep_apply_cb_reached"; + +--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; + +--connection node_2a +SET DEBUG_SYNC = "RESET"; 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..442a7113537 --- /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 mysql.wsrep_streaming_log; +--connection node_2 +SELECT COUNT(*) = 0 from mysql.wsrep_streaming_log; + +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/sys_vars/r/sysvars_wsrep.result b/mysql-test/suite/sys_vars/r/sysvars_wsrep.result index db932ae8223..ac83a0a8c7f 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_wsrep.result +++ b/mysql-test/suite/sys_vars/r/sysvars_wsrep.result @@ -211,6 +211,20 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME WSREP_IGNORE_APPLY_ERRORS +SESSION_VALUE NULL +GLOBAL_VALUE 7 +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE 7 +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE INT UNSIGNED +VARIABLE_COMMENT Ignore replication errors +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 7 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME WSREP_LOAD_DATA_SPLITTING SESSION_VALUE NULL GLOBAL_VALUE ON @@ -218,7 +232,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE ON VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT To commit LOAD DATA transaction after every 10K rows inserted +VARIABLE_COMMENT To commit LOAD DATA transaction after every 10K rows inserted (deprecating) NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL @@ -519,6 +533,20 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME WSREP_SR_STORE +SESSION_VALUE NULL +GLOBAL_VALUE table +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE table +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE ENUM +VARIABLE_COMMENT Storage for streaming replication fragments +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST none,table +READ_ONLY YES +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME WSREP_SST_AUTH SESSION_VALUE NULL GLOBAL_VALUE @@ -617,3 +645,31 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME WSREP_TRX_FRAGMENT_SIZE +SESSION_VALUE 0 +GLOBAL_VALUE 0 +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE 0 +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT Size of transaction fragments for streaming replication (measured in units of 'wsrep_trx_fragment_unit') +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 2147483647 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME WSREP_TRX_FRAGMENT_UNIT +SESSION_VALUE bytes +GLOBAL_VALUE bytes +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE bytes +VARIABLE_SCOPE SESSION +VARIABLE_TYPE ENUM +VARIABLE_COMMENT Unit for streaming replication transaction fragments' size: bytes, rows, statements +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST bytes,rows,statements +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED diff --git a/mysql-test/suite/sys_vars/r/wsrep_provider_options_basic.result b/mysql-test/suite/sys_vars/r/wsrep_provider_options_basic.result index b2e07c55b38..15949a14e39 100644 --- a/mysql-test/suite/sys_vars/r/wsrep_provider_options_basic.result +++ b/mysql-test/suite/sys_vars/r/wsrep_provider_options_basic.result @@ -2,9 +2,6 @@ # wsrep_provider_options # call mtr.add_suppression("WSREP: Failed to get provider options"); -SET @@global.wsrep_provider = @@global.wsrep_provider; -# save the initial value -SET @wsrep_provider_options_global_saved = @@global.wsrep_provider_options; # default SELECT @@global.wsrep_provider_options; @@global.wsrep_provider_options @@ -16,18 +13,21 @@ ERROR HY000: Variable 'wsrep_provider_options' is a GLOBAL variable SET @@global.wsrep_provider_options='option1'; SELECT @@global.wsrep_provider_options; @@global.wsrep_provider_options -option1 + # valid values SET @@global.wsrep_provider_options='name1=value1;name2=value2'; +ERROR HY000: WSREP (galera) not started SELECT @@global.wsrep_provider_options; @@global.wsrep_provider_options -name1=value1;name2=value2 + SET @@global.wsrep_provider_options='hyphenated-name:value'; +ERROR HY000: WSREP (galera) not started SELECT @@global.wsrep_provider_options; @@global.wsrep_provider_options -hyphenated-name:value + SET @@global.wsrep_provider_options=default; +ERROR HY000: WSREP (galera) not started SELECT @@global.wsrep_provider_options; @@global.wsrep_provider_options @@ -42,8 +42,5 @@ SET @@global.wsrep_provider_options=NULL; Got one of the listed errors SELECT @@global.wsrep_provider_options; @@global.wsrep_provider_options -NULL -# restore the initial value -SET @@global.wsrep_provider_options = @wsrep_provider_options_global_saved; # End of test diff --git a/mysql-test/suite/sys_vars/t/wsrep_provider_options_basic.test b/mysql-test/suite/sys_vars/t/wsrep_provider_options_basic.test index d2ea32a0637..6eb3a94b6a4 100644 --- a/mysql-test/suite/sys_vars/t/wsrep_provider_options_basic.test +++ b/mysql-test/suite/sys_vars/t/wsrep_provider_options_basic.test @@ -6,11 +6,6 @@ call mtr.add_suppression("WSREP: Failed to get provider options"); -SET @@global.wsrep_provider = @@global.wsrep_provider; - ---echo # save the initial value -SET @wsrep_provider_options_global_saved = @@global.wsrep_provider_options; - --echo # default SELECT @@global.wsrep_provider_options; @@ -24,13 +19,13 @@ SELECT @@global.wsrep_provider_options; --echo --echo # valid values ---error 0,ER_WRONG_ARGUMENTS +--error ER_WRONG_ARGUMENTS SET @@global.wsrep_provider_options='name1=value1;name2=value2'; SELECT @@global.wsrep_provider_options; ---error 0,ER_WRONG_ARGUMENTS +--error ER_WRONG_ARGUMENTS SET @@global.wsrep_provider_options='hyphenated-name:value'; SELECT @@global.wsrep_provider_options; ---error 0,ER_WRONG_ARGUMENTS +--error ER_WRONG_ARGUMENTS SET @@global.wsrep_provider_options=default; SELECT @@global.wsrep_provider_options; @@ -43,9 +38,4 @@ SELECT @@global.wsrep_provider_options; SET @@global.wsrep_provider_options=NULL; SELECT @@global.wsrep_provider_options; ---echo ---echo # restore the initial value ---error 0,ER_WRONG_ARGUMENTS -SET @@global.wsrep_provider_options = @wsrep_provider_options_global_saved; - --echo # End of test diff --git a/mysql-test/suite/wsrep/disabled.def b/mysql-test/suite/wsrep/disabled.def index 24d46cc39f0..61142398372 100644 --- a/mysql-test/suite/wsrep/disabled.def +++ b/mysql-test/suite/wsrep/disabled.def @@ -1,2 +1,3 @@ wsrep.foreign_key : Sporadic failure "WSREP has not yet prepared node for application use" wsrep.pool_of_threads : Sporadic failure "WSREP has not yet prepared node for application use" +wsrep.variables : Global wsrep_on manipulation causes debug asserts diff --git a/mysql-test/suite/wsrep/my.cnf b/mysql-test/suite/wsrep/my.cnf index 7e51b0750a1..e90686850a9 100644 --- a/mysql-test/suite/wsrep/my.cnf +++ b/mysql-test/suite/wsrep/my.cnf @@ -1,10 +1,8 @@ # Use default setting for mysqld processes !include include/default_mysqld.cnf -[mysqld] -wsrep-on=1 - [mysqld.1] +wsrep-on=OFF #galera_port=@OPT.port #ist_port=@OPT.port #sst_port=@OPT.port diff --git a/mysql-test/suite/wsrep/r/wsrep-recover,binlogon.rdiff b/mysql-test/suite/wsrep/r/wsrep-recover,binlogon.rdiff new file mode 100644 index 00000000000..8b1b1e4c035 --- /dev/null +++ b/mysql-test/suite/wsrep/r/wsrep-recover,binlogon.rdiff @@ -0,0 +1,28 @@ +--- r/wsrep-recover.result 2019-01-11 16:22:46.329012579 +0200 ++++ r/wsrep-recover.reject 2019-01-11 16:23:55.313137675 +0200 +@@ -48,19 +48,17 @@ + SET DEBUG_SYNC = "now WAIT_FOR before_commit_order_reached_1"; + connection default; + # Kill the server +-Expect seqno 9 +-9 ++Expect seqno 7 ++7 + disconnect con1; + disconnect con2; + disconnect con_ctrl; + connection default; +-SELECT VARIABLE_VALUE `expect 10` FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'; +-expect 10 +-10 +-Expect rows 5, 9, 10 ++SELECT VARIABLE_VALUE `expect 8` FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'; ++expect 8 ++8 ++Expect row 5 + SELECT * FROM t1; + f1 + 5 +-9 +-10 + DROP TABLE t1; diff --git a/mysql-test/suite/wsrep/r/wsrep-recover.result b/mysql-test/suite/wsrep/r/wsrep-recover.result new file mode 100644 index 00000000000..10ad4e58fc5 --- /dev/null +++ b/mysql-test/suite/wsrep/r/wsrep-recover.result @@ -0,0 +1,66 @@ +# Kill the server +Expect seqno 1 +1 +CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; +# Kill the server +Expect seqno 3 +3 +INSERT INTO t1 VALUES (5); +# Kill the server +Expect seqno 5 +5 +SELECT VARIABLE_VALUE `expect 6` FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'; +expect 6 +6 +connect con1, localhost, root; +SET DEBUG_SYNC = "wsrep_after_certification SIGNAL after_certification_reached WAIT_FOR continue"; +INSERT INTO t1 VALUES (7); +connect con_ctrl, localhost, root; +SET DEBUG_SYNC = "now WAIT_FOR after_certification_reached"; +connect con2, localhost, root; +SET DEBUG_SYNC = "wsrep_before_commit_order_enter SIGNAL before_commit_order_reached WAIT_FOR continue"; +INSERT INTO t1 VALUES (8); +connection con_ctrl; +SET DEBUG_SYNC = "now WAIT_FOR before_commit_order_reached"; +connection default; +# Kill the server +Expect seqno 6 +6 +disconnect con1; +disconnect con2; +disconnect con_ctrl; +connection default; +SELECT VARIABLE_VALUE `expect 7` FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'; +expect 7 +7 +connect con1, localhost, root; +SET DEBUG_SYNC = "wsrep_after_certification SIGNAL after_certification_reached WAIT_FOR continue_after_certification"; +SET DEBUG_SYNC = "wsrep_before_commit_order_enter SIGNAL before_commit_order_reached_1 WAIT_FOR continue_before_commit_order_1"; +INSERT INTO t1 VALUES (9); +connect con_ctrl, localhost, root; +SET DEBUG_SYNC = "now WAIT_FOR after_certification_reached"; +connect con2, localhost, root; +SET DEBUG_SYNC = "wsrep_before_commit_order_enter SIGNAL before_commit_order_reached_2 WAIT_FOR continue_before_commit_order_2"; +INSERT INTO t1 VALUES (10); +connection con_ctrl; +SET DEBUG_SYNC = "now WAIT_FOR before_commit_order_reached_2"; +SET DEBUG_SYNC = "now SIGNAL continue_after_certification"; +SET DEBUG_SYNC = "now WAIT_FOR before_commit_order_reached_1"; +connection default; +# Kill the server +Expect seqno 9 +9 +disconnect con1; +disconnect con2; +disconnect con_ctrl; +connection default; +SELECT VARIABLE_VALUE `expect 10` FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'; +expect 10 +10 +Expect rows 5, 9, 10 +SELECT * FROM t1; +f1 +5 +9 +10 +DROP TABLE t1; diff --git a/mysql-test/suite/wsrep/suite.pm b/mysql-test/suite/wsrep/suite.pm index 03e23b8d7cb..fbaf5aa2b22 100644 --- a/mysql-test/suite/wsrep/suite.pm +++ b/mysql-test/suite/wsrep/suite.pm @@ -9,9 +9,9 @@ return "Not run for embedded server" if $::opt_embedded_server; return "WSREP is not compiled in" unless defined $::mysqld_variables{'wsrep-on'}; my ($provider) = grep { -f $_ } $ENV{WSREP_PROVIDER}, - "/usr/lib64/galera-3/libgalera_smm.so", + "/usr/lib64/galera-4/libgalera_smm.so", "/usr/lib64/galera/libgalera_smm.so", - "/usr/lib/galera-3/libgalera_smm.so", + "/usr/lib/galera-4/libgalera_smm.so", "/usr/lib/galera/libgalera_smm.so"; return "No wsrep provider library" unless -f $provider; diff --git a/mysql-test/suite/wsrep/t/binlog_format.cnf b/mysql-test/suite/wsrep/t/binlog_format.cnf new file mode 100644 index 00000000000..7ec24c14d80 --- /dev/null +++ b/mysql-test/suite/wsrep/t/binlog_format.cnf @@ -0,0 +1,8 @@ +!include ../my.cnf + +[mysqld.1] +wsrep-on=ON +wsrep-provider=@ENV.WSREP_PROVIDER +wsrep-cluster-address=gcomm:// +innodb_autoinc_lock_mode=2 + diff --git a/mysql-test/suite/wsrep/t/binlog_format.opt b/mysql-test/suite/wsrep/t/binlog_format.opt deleted file mode 100644 index e3f2470c6e5..00000000000 --- a/mysql-test/suite/wsrep/t/binlog_format.opt +++ /dev/null @@ -1 +0,0 @@ ---innodb_autoinc_lock_mode=2 --wsrep-provider=$WSREP_PROVIDER --wsrep-cluster-address=gcomm:// diff --git a/mysql-test/suite/wsrep/t/binlog_format.test b/mysql-test/suite/wsrep/t/binlog_format.test index 07001b17a84..695859a2ad3 100644 --- a/mysql-test/suite/wsrep/t/binlog_format.test +++ b/mysql-test/suite/wsrep/t/binlog_format.test @@ -1,3 +1,4 @@ +--source include/have_innodb.inc --source include/have_wsrep_provider.inc --source include/have_binlog_format_row.inc diff --git a/mysql-test/suite/wsrep/t/mdev_10186.cnf b/mysql-test/suite/wsrep/t/mdev_10186.cnf new file mode 100644 index 00000000000..3c4ca003f76 --- /dev/null +++ b/mysql-test/suite/wsrep/t/mdev_10186.cnf @@ -0,0 +1,6 @@ +!include ../my.cnf + +[mysqld.1] +wsrep-on=OFF +wsrep-provider=@ENV.WSREP_PROVIDER +wsrep-cluster-address=gcomm:// diff --git a/mysql-test/suite/wsrep/t/mdev_10186.opt b/mysql-test/suite/wsrep/t/mdev_10186.opt deleted file mode 100644 index e2655959c62..00000000000 --- a/mysql-test/suite/wsrep/t/mdev_10186.opt +++ /dev/null @@ -1 +0,0 @@ ---wsrep-provider=$WSREP_PROVIDER --wsrep-cluster-address=gcomm:// --wsrep-on=0 diff --git a/mysql-test/suite/wsrep/t/mdev_10186.test b/mysql-test/suite/wsrep/t/mdev_10186.test index 98ea5192634..f86c69f8a5b 100644 --- a/mysql-test/suite/wsrep/t/mdev_10186.test +++ b/mysql-test/suite/wsrep/t/mdev_10186.test @@ -1,3 +1,4 @@ +--source include/have_innodb.inc --source include/have_wsrep_provider.inc --source include/have_binlog_format_row.inc diff --git a/mysql-test/suite/wsrep/t/mdev_6832.cnf b/mysql-test/suite/wsrep/t/mdev_6832.cnf new file mode 100644 index 00000000000..0bf01f81fc5 --- /dev/null +++ b/mysql-test/suite/wsrep/t/mdev_6832.cnf @@ -0,0 +1,7 @@ +!include ../my.cnf + +[mysqld.1] +wsrep-on=ON +wsrep-provider=@ENV.WSREP_PROVIDER +wsrep-cluster-address=gcomm:// + diff --git a/mysql-test/suite/wsrep/t/mdev_6832.opt b/mysql-test/suite/wsrep/t/mdev_6832.opt deleted file mode 100644 index 16f8962dba2..00000000000 --- a/mysql-test/suite/wsrep/t/mdev_6832.opt +++ /dev/null @@ -1 +0,0 @@ ---wsrep-provider=$WSREP_PROVIDER --wsrep-cluster-address=gcomm:// --wsrep-on=1 diff --git a/mysql-test/suite/wsrep/t/mdev_6832.test b/mysql-test/suite/wsrep/t/mdev_6832.test index 9efccface57..226be1b788c 100644 --- a/mysql-test/suite/wsrep/t/mdev_6832.test +++ b/mysql-test/suite/wsrep/t/mdev_6832.test @@ -1,3 +1,4 @@ +--source include/have_innodb.inc --source include/have_wsrep_provider.inc --source include/have_binlog_format_row.inc diff --git a/mysql-test/suite/wsrep/t/mdev_7798.cnf b/mysql-test/suite/wsrep/t/mdev_7798.cnf new file mode 100644 index 00000000000..0bf01f81fc5 --- /dev/null +++ b/mysql-test/suite/wsrep/t/mdev_7798.cnf @@ -0,0 +1,7 @@ +!include ../my.cnf + +[mysqld.1] +wsrep-on=ON +wsrep-provider=@ENV.WSREP_PROVIDER +wsrep-cluster-address=gcomm:// + diff --git a/mysql-test/suite/wsrep/t/mdev_7798.opt b/mysql-test/suite/wsrep/t/mdev_7798.opt deleted file mode 100644 index 1007d5c0b78..00000000000 --- a/mysql-test/suite/wsrep/t/mdev_7798.opt +++ /dev/null @@ -1 +0,0 @@ ---wsrep-provider=$WSREP_PROVIDER --wsrep-cluster-address=gcomm:// --wsrep-on=1 diff --git a/mysql-test/suite/wsrep/t/mdev_7798.test b/mysql-test/suite/wsrep/t/mdev_7798.test index 9dfff0959bc..b9938d936cc 100644 --- a/mysql-test/suite/wsrep/t/mdev_7798.test +++ b/mysql-test/suite/wsrep/t/mdev_7798.test @@ -1,3 +1,4 @@ +--source include/have_innodb.inc --source include/have_wsrep_provider.inc --source include/have_binlog_format_row.inc diff --git a/mysql-test/suite/wsrep/t/pool_of_threads.cnf b/mysql-test/suite/wsrep/t/pool_of_threads.cnf new file mode 100644 index 00000000000..b63e3324796 --- /dev/null +++ b/mysql-test/suite/wsrep/t/pool_of_threads.cnf @@ -0,0 +1,8 @@ +!include ../my.cnf + +[mysqld.1] +wsrep-on=ON +wsrep-provider=@ENV.WSREP_PROVIDER +wsrep-cluster-address=gcomm:// +thread_handling=pool-of-threads + diff --git a/mysql-test/suite/wsrep/t/pool_of_threads.opt b/mysql-test/suite/wsrep/t/pool_of_threads.opt deleted file mode 100644 index 814417e5b0f..00000000000 --- a/mysql-test/suite/wsrep/t/pool_of_threads.opt +++ /dev/null @@ -1 +0,0 @@ ---innodb_autoinc_lock_mode=2 --wsrep-provider=$WSREP_PROVIDER --wsrep-cluster-address=gcomm:// --thread_handling=pool-of-threads diff --git a/mysql-test/suite/wsrep/t/wsrep-recover-step.inc b/mysql-test/suite/wsrep/t/wsrep-recover-step.inc new file mode 100644 index 00000000000..22669438fe0 --- /dev/null +++ b/mysql-test/suite/wsrep/t/wsrep-recover-step.inc @@ -0,0 +1,41 @@ +# +# Macro to run wsrep recovery step. This is adapted from +# suite/galera/include/galera_wsrep_recover.inc, with additional +# option to pass binlog argument to recovery command. The macro +# returns recovered position split in uuid and seqno parts. +# +# Arguments: +# +# wsrep_recover_binlog_opt - Binlog options to recovery command +# +# Return: +# +# wsrep_recover_start_position_uuid - UUID corresponding to recovered position +# wsrep_recover_start_position_seqno - seqno corresponding to recovered position +# + +--exec $MYSQLD --defaults-group-suffix=.1 --defaults-file=$MYSQLTEST_VARDIR/my.cnf --log-error=$MYSQL_TMP_DIR/galera_wsrep_recover.log --innodb --wsrep-recover $wsrep_recover_binlog_opt --core-file > $MYSQL_TMP_DIR/galera_wsrep_recover.log 2>&1 + +--perl + use strict; + my $wsrep_start_position = `grep 'WSREP: Recovered position:' $ENV{MYSQL_TMP_DIR}/galera_wsrep_recover.log | sed 's/.*WSREP\:\ Recovered\ position://' | sed 's/^[ \t]*//'`; + chomp($wsrep_start_position); + die if $wsrep_start_position eq ''; + open(FILE, ">", "$ENV{MYSQL_TMP_DIR}/galera_wsrep_start_position.inc") or die; + my ($uuid, $seqno) = split /:/, $wsrep_start_position; + print FILE "--let \$wsrep_recover_start_position_uuid = $uuid\n"; + print FILE "--let \$wsrep_recover_start_position_seqno = $seqno\n"; + close FILE; +EOF + +--source $MYSQL_TMP_DIR/galera_wsrep_start_position.inc + +if ($wsrep_recover_start_position_uuid == '') { + --die "Could not obtain start_position_uuid." +} + +if ($wsrep_recover_start_position_seqno == '') { + --die "Could not obtain start_position_seqno." +} + +--remove_file $MYSQL_TMP_DIR/galera_wsrep_start_position.inc diff --git a/mysql-test/suite/wsrep/t/wsrep-recover.cnf b/mysql-test/suite/wsrep/t/wsrep-recover.cnf new file mode 100644 index 00000000000..19986cd97bc --- /dev/null +++ b/mysql-test/suite/wsrep/t/wsrep-recover.cnf @@ -0,0 +1,9 @@ +!include ../my.cnf + +[mysqld.1] +wsrep-on=ON +binlog-format=ROW +innodb-flush-log-at-trx-commit=1 +wsrep-cluster-address=gcomm:// +wsrep-provider=@ENV.WSREP_PROVIDER +innodb-autoinc-lock-mode=2
\ No newline at end of file diff --git a/mysql-test/suite/wsrep/t/wsrep-recover.combinations b/mysql-test/suite/wsrep/t/wsrep-recover.combinations new file mode 100644 index 00000000000..1ce3b45aa1a --- /dev/null +++ b/mysql-test/suite/wsrep/t/wsrep-recover.combinations @@ -0,0 +1,4 @@ +[binlogon] +log-bin + +[binlogoff] diff --git a/mysql-test/suite/wsrep/t/wsrep-recover.test b/mysql-test/suite/wsrep/t/wsrep-recover.test new file mode 100644 index 00000000000..8f00f19c27f --- /dev/null +++ b/mysql-test/suite/wsrep/t/wsrep-recover.test @@ -0,0 +1,204 @@ +# +# Verify that the wsrep XID gets updated in InnoDB rollback segment +# properly and can be recovered with --wsrep-recover +# +# The test runs the following scenarios: +# +# 1) The server is started but no SQL is run +# 2) DDL is executed +# 3) INSERT is executed +# 4) Two INSERTs are executed so that the first one in order will be +# blocked after certification and the second one before entering +# commit order critical section. +# 5) Two DMLs are executed so that the prepare step is run out of order. +# Both transactions are blocked before commit order critical section. +# +# After each scenario server is killed and the recovered position +# is validated. +# + +--source include/have_wsrep.inc +--source include/have_innodb.inc +--source include/have_wsrep_provider.inc +--source include/have_debug_sync.inc + +# +# Binlog option for recovery run. This must be set in the test because +# combinations file causes log-bin option to be set from command line, +# not via my.cnf. +# +--let $log_bin = `SELECT @@log_bin` +if ($log_bin) { +--let $wsrep_recover_binlog_opt = --log-bin +} + +# +# Scenario 1 +# The expected recovered seqno is 1 corresponding to initial cluster +# configuration change. +# +--source include/kill_mysqld.inc +--source wsrep-recover-step.inc +--echo Expect seqno 1 +--echo $wsrep_recover_start_position_seqno + +--let $restart_parameters = --wsrep-start-position=$wsrep_recover_start_position_uuid:$wsrep_recover_start_position_seqno +--source include/start_mysqld.inc +--source include/wait_wsrep_ready.inc + +# +# Senario 2 +# The expected recovered seqno is 3 corresponding to two configuration +# change events and CREATE TABLE. +# + +CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; +--source include/kill_mysqld.inc +--source wsrep-recover-step.inc +--echo Expect seqno 3 +--echo $wsrep_recover_start_position_seqno + +--let $restart_parameters = --wsrep-start-position=$wsrep_recover_start_position_uuid:$wsrep_recover_start_position_seqno +--source include/start_mysqld.inc +--source include/wait_wsrep_ready.inc + +# +# Scenario 3 +# The expected recovered seqno is 5 corresponding to three configuration +# change events, CREATE TABLE and INSERT. +# +# The expected wsrep_last_committed after the server is restarted is 6. +# + +INSERT INTO t1 VALUES (5); +--source include/kill_mysqld.inc +--source wsrep-recover-step.inc +--echo Expect seqno 5 +--echo $wsrep_recover_start_position_seqno +--let $restart_parameters = --wsrep-start-position=$wsrep_recover_start_position_uuid:$wsrep_recover_start_position_seqno +--source include/start_mysqld.inc +--source include/wait_wsrep_ready.inc + +SELECT VARIABLE_VALUE `expect 6` FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'; + +# +# Scenario 4 +# +# This will cause the following +# +# Seqno 7 - the first INSERT is blocked after it is certified but before +# it gets prepared +# Seqno 8 - the second INSERT is blocked before it will be ordered for +# commit, so it becomes prepared +# +# As an outcome, the recovery process should return seqno 6 because +# the range of prepared transactions found after the crash recovery +# is not continuous up to 8. +# +# The expected wsrep_last_committed after server is restarted is 7. +# + +# Send INSERT which will block after certification +--connect con1, localhost, root +SET DEBUG_SYNC = "wsrep_after_certification SIGNAL after_certification_reached WAIT_FOR continue"; +--send INSERT INTO t1 VALUES (7) + +--connect con_ctrl, localhost, root +SET DEBUG_SYNC = "now WAIT_FOR after_certification_reached"; + +# Send INSERT which will block before commit order critical section +--connect con2, localhost, root +SET DEBUG_SYNC = "wsrep_before_commit_order_enter SIGNAL before_commit_order_reached WAIT_FOR continue"; +--send INSERT INTO t1 VALUES (8) + +--connection con_ctrl +SET DEBUG_SYNC = "now WAIT_FOR before_commit_order_reached"; + +--connection default +--source include/kill_mysqld.inc +--source wsrep-recover-step.inc +--echo Expect seqno 6 +--echo $wsrep_recover_start_position_seqno +--let $restart_parameters = --wsrep-start-position=$wsrep_recover_start_position_uuid:$wsrep_recover_start_position_seqno +--source include/start_mysqld.inc +--source include/wait_wsrep_ready.inc + +--disconnect con1 +--disconnect con2 +--disconnect con_ctrl +--connection default + +SELECT VARIABLE_VALUE `expect 7` FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'; + +# +# Scenario 5 +# +# This scenario will run two INSERTs in parallel so that they are +# prepared out of order. The execution is stopped before commit +# and the server is killed. The outcome of this scenario depends +# on binlog settings: +# +# If binlog is off, the transactions will be recovered from InnoDB and +# committed during recovery. The expected recovered seqno is 9, the +# expected wsrep_last_committed after server is restarted is 10. +# +# If binlog is on, the transactions will be recovered from InnoDB but +# will be rolled back since they are not logged yet in binlog. The +# expected recovered seqno is 7, the expected wsrep_last_committed +# after server is restarted is 8. +# + +--connect con1, localhost, root +SET DEBUG_SYNC = "wsrep_after_certification SIGNAL after_certification_reached WAIT_FOR continue_after_certification"; +SET DEBUG_SYNC = "wsrep_before_commit_order_enter SIGNAL before_commit_order_reached_1 WAIT_FOR continue_before_commit_order_1"; +--send INSERT INTO t1 VALUES (9) + +--connect con_ctrl, localhost, root +SET DEBUG_SYNC = "now WAIT_FOR after_certification_reached"; + +--connect con2, localhost, root +SET DEBUG_SYNC = "wsrep_before_commit_order_enter SIGNAL before_commit_order_reached_2 WAIT_FOR continue_before_commit_order_2"; +--send INSERT INTO t1 VALUES (10) + +--connection con_ctrl +SET DEBUG_SYNC = "now WAIT_FOR before_commit_order_reached_2"; +SET DEBUG_SYNC = "now SIGNAL continue_after_certification"; +SET DEBUG_SYNC = "now WAIT_FOR before_commit_order_reached_1"; + +--connection default +--source include/kill_mysqld.inc +--source wsrep-recover-step.inc +if ($log_bin) { + --echo Expect seqno 7 +} +if (!$log_bin) { + --echo Expect seqno 9 +} +--echo $wsrep_recover_start_position_seqno +--let $restart_parameters = --wsrep-start-position=$wsrep_recover_start_position_uuid:$wsrep_recover_start_position_seqno +--source include/start_mysqld.inc +--source include/wait_wsrep_ready.inc + +--disconnect con1 +--disconnect con2 +--disconnect con_ctrl +--connection default + +if ($log_bin) { + SELECT VARIABLE_VALUE `expect 8` FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'; +} +if (!$log_bin) { + SELECT VARIABLE_VALUE `expect 10` FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'; +} + +# +# Final sanity check: The successful inserts into t1 should result +if ($log_bin) { + --echo Expect row 5 +} +if (!$log_bin) { + --echo Expect rows 5, 9, 10 +} +SELECT * FROM t1; + +DROP TABLE t1; diff --git a/plugin/wsrep_info/mysql-test/wsrep_info/my.cnf b/plugin/wsrep_info/mysql-test/wsrep_info/my.cnf index 70682178ca1..1c7a8ad4122 100644 --- a/plugin/wsrep_info/mysql-test/wsrep_info/my.cnf +++ b/plugin/wsrep_info/mysql-test/wsrep_info/my.cnf @@ -2,23 +2,26 @@ !include include/default_mysqld.cnf [mysqld] -wsrep-on=1 binlog-format=row innodb-autoinc-lock-mode=2 innodb-locks-unsafe-for-binlog=1 -wsrep-cluster-address=gcomm:// wsrep_provider=@ENV.WSREP_PROVIDER [mysqld.1] #galera_port=@OPT.port +#ist_port=@OPT.port #sst_port=@OPT.port +wsrep-on=1 +wsrep-cluster-address=gcomm:// wsrep_provider_options='base_port=@mysqld.1.#galera_port' wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' wsrep_node_name=test-node-1 [mysqld.2] #galera_port=@OPT.port +#ist_port=@OPT.port #sst_port=@OPT.port +wsrep-on=1 wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' wsrep_provider_options='base_port=@mysqld.2.#galera_port' wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' diff --git a/plugin/wsrep_info/mysql-test/wsrep_info/r/plugin.result b/plugin/wsrep_info/mysql-test/wsrep_info/r/plugin.result index f33a628d428..f99f27f3539 100644 --- a/plugin/wsrep_info/mysql-test/wsrep_info/r/plugin.result +++ b/plugin/wsrep_info/mysql-test/wsrep_info/r/plugin.result @@ -1,8 +1,10 @@ +connection node_2; +connection node_1; # On node 1 connection node_1; SELECT * FROM INFORMATION_SCHEMA.WSREP_STATUS; -NODE_INDEX NODE_STATUS CLUSTER_STATUS CLUSTER_SIZE CLUSTER_STATE_UUID CLUSTER_STATE_SEQNO CLUSTER_CONF_ID GAP PROTOCOL_VERSION -<IDX> Synced Primary 2 <CLUSTER_STATE_UUID> 0 <CLUSTER_CONF_ID> NO 3 +NODE_INDEX NODE_STATUS CLUSTER_STATUS CLUSTER_SIZE CLUSTER_STATE_UUID CLUSTER_STATE_SEQNO CLUSTER_CONF_ID PROTOCOL_VERSION +<IDX> synced primary 2 <CLUSTER_STATE_UUID> 2 <CLUSTER_CONF_ID> 4 SELECT * FROM INFORMATION_SCHEMA.WSREP_MEMBERSHIP ORDER BY NAME; INDEX UUID NAME ADDRESS <IDX> <MEMBER_ID> test-node-1 <ADDRESS> @@ -10,8 +12,8 @@ INDEX UUID NAME ADDRESS # On node 2 connection node_2; SELECT * FROM INFORMATION_SCHEMA.WSREP_STATUS; -NODE_INDEX NODE_STATUS CLUSTER_STATUS CLUSTER_SIZE CLUSTER_STATE_UUID CLUSTER_STATE_SEQNO CLUSTER_CONF_ID GAP PROTOCOL_VERSION -<IDX> Synced Primary 2 <CLUSTER_STATE_UUID> 0 <CLUSTER_CONF_ID> YES 3 +NODE_INDEX NODE_STATUS CLUSTER_STATUS CLUSTER_SIZE CLUSTER_STATE_UUID CLUSTER_STATE_SEQNO CLUSTER_CONF_ID PROTOCOL_VERSION +<IDX> synced primary 2 <CLUSTER_STATE_UUID> 2 <CLUSTER_CONF_ID> 4 SELECT * FROM INFORMATION_SCHEMA.WSREP_MEMBERSHIP ORDER BY NAME; INDEX UUID NAME ADDRESS <IDX> <MEMBER_ID> test-node-1 <ADDRESS> diff --git a/plugin/wsrep_info/mysql-test/wsrep_info/suite.pm b/plugin/wsrep_info/mysql-test/wsrep_info/suite.pm index 9268cb3e06b..2adc6811f3f 100644 --- a/plugin/wsrep_info/mysql-test/wsrep_info/suite.pm +++ b/plugin/wsrep_info/mysql-test/wsrep_info/suite.pm @@ -9,9 +9,9 @@ return "Not run for embedded server" if $::opt_embedded_server; return "WSREP is not compiled in" unless defined $::mysqld_variables{'wsrep-on'}; my ($provider) = grep { -f $_ } $ENV{WSREP_PROVIDER}, - "/usr/lib64/galera-3/libgalera_smm.so", + "/usr/lib64/galera-4/libgalera_smm.so", "/usr/lib64/galera/libgalera_smm.so", - "/usr/lib/galera-3/libgalera_smm.so", + "/usr/lib/galera-4/libgalera_smm.so", "/usr/lib/galera/libgalera_smm.so"; return "No wsrep provider library" unless -f $provider; diff --git a/plugin/wsrep_info/plugin.cc b/plugin/wsrep_info/plugin.cc index 428bcc5dcfc..18e41b20c98 100644 --- a/plugin/wsrep_info/plugin.cc +++ b/plugin/wsrep_info/plugin.cc @@ -52,37 +52,9 @@ #define COLUMN_WSREP_STATUS_CLUSTER_STATE_SEQNO 5 /* Cluster membership changes */ #define COLUMN_WSREP_STATUS_CLUSTER_CONF_ID 6 -/* Gap between global and local states ? */ -#define COLUMN_WSREP_STATUS_GAP 7 /* Application protocol version */ -#define COLUMN_WSREP_STATUS_PROTO_VERSION 8 +#define COLUMN_WSREP_STATUS_PROTO_VERSION 7 -static const char* get_member_status(wsrep_member_status_t status) -{ - switch (status) - { - case WSREP_MEMBER_UNDEFINED: return "Undefined"; - case WSREP_MEMBER_JOINER: return "Joiner"; - case WSREP_MEMBER_DONOR: return "Donor"; - case WSREP_MEMBER_JOINED: return "Joined"; - case WSREP_MEMBER_SYNCED: return "Synced"; - case WSREP_MEMBER_ERROR: return "Error"; - default: break; - } - return "UNKNOWN"; -} - -static const char* get_cluster_status(wsrep_view_status_t status) -{ - switch (status) - { - case WSREP_VIEW_PRIMARY: return "Primary"; - case WSREP_VIEW_NON_PRIMARY: return "Non-primary"; - case WSREP_VIEW_DISCONNECTED: return "Disconnected"; - default: break; - } - return "UNKNOWN"; -} static ST_FIELD_INFO wsrep_memb_fields[]= { @@ -107,7 +79,6 @@ static ST_FIELD_INFO wsrep_status_fields[]= 0, 0, 0, 0}, {"CLUSTER_CONF_ID", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, 0, 0}, - {"GAP", 10, MYSQL_TYPE_STRING, 0, 0, 0, 0}, {"PROTOCOL_VERSION", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, 0, 0}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} @@ -122,25 +93,26 @@ static int wsrep_memb_fill_table(THD *thd, TABLE_LIST *tables, COND *cond) wsrep_config_state->lock(); - Dynamic_array<wsrep_member_info_t> *memb_arr= - wsrep_config_state->get_member_info(); + const wsrep::view& view(wsrep_config_state->get_view_info()); + const std::vector<wsrep::view::member>& members(view.members()); + TABLE *table= tables->table; - for (unsigned int i= 0; i < memb_arr->elements(); i ++) + for (unsigned int i= 0; i < members.size(); i++) { - wsrep_member_info_t memb= memb_arr->at(i); - table->field[COLUMN_WSREP_MEMB_INDEX]->store(i, 0); - char uuid[40]; - wsrep_uuid_print(&memb.id, uuid, sizeof(uuid)); - table->field[COLUMN_WSREP_MEMB_UUID]->store(uuid, sizeof(uuid), + std::ostringstream os; + os << members[i].id(); + table->field[COLUMN_WSREP_MEMB_UUID]->store(os.str().c_str(), + os.str().length(), system_charset_info); - table->field[COLUMN_WSREP_MEMB_NAME]->store(memb.name, strlen(memb.name), + table->field[COLUMN_WSREP_MEMB_NAME]->store(members[i].name().c_str(), + members[i].name().length(), system_charset_info); - table->field[COLUMN_WSREP_MEMB_ADDRESS]->store(memb.incoming, - strlen(memb.incoming), + table->field[COLUMN_WSREP_MEMB_ADDRESS]->store(members[i].incoming().c_str(), + members[i].incoming().length(), system_charset_info); if (schema_table_store_record(thd, table)) @@ -177,35 +149,34 @@ static int wsrep_status_fill_table(THD *thd, TABLE_LIST *tables, COND *cond) wsrep_config_state->lock(); - wsrep_view_info_t view= wsrep_config_state->get_view_info(); - wsrep_member_status_t status= wsrep_config_state->get_status(); + const wsrep::view& view= wsrep_config_state->get_view_info(); + enum wsrep::server_state::state status= wsrep_config_state->get_status(); TABLE *table= tables->table; table->field[COLUMN_WSREP_STATUS_NODE_INDEX] - ->store(view.my_idx, 0); + ->store(view.own_index(), 0); table->field[COLUMN_WSREP_STATUS_NODE_STATUS] - ->store(get_member_status(status), strlen(get_member_status(status)), + ->store(to_c_string(status), + strlen(to_c_string(status)), system_charset_info); table->field[COLUMN_WSREP_STATUS_CLUSTER_STATUS] - ->store(get_cluster_status(view.status), - strlen(get_cluster_status(view.status)), + ->store(to_c_string(view.status()), + strlen(to_c_string(view.status())), system_charset_info); - table->field[COLUMN_WSREP_STATUS_CLUSTER_SIZE]->store(view.memb_num, 0); + table->field[COLUMN_WSREP_STATUS_CLUSTER_SIZE]->store(view.members().size(), 0); - char uuid[40]; - wsrep_uuid_print(&view.state_id.uuid, uuid, sizeof(uuid)); + std::ostringstream os; + os << view.state_id().id(); table->field[COLUMN_WSREP_STATUS_CLUSTER_STATE_UUID] - ->store(uuid, sizeof(uuid), system_charset_info); + ->store(os.str().c_str(), os.str().length(), system_charset_info); table->field[COLUMN_WSREP_STATUS_CLUSTER_STATE_SEQNO] - ->store(view.state_id.seqno, 0); - table->field[COLUMN_WSREP_STATUS_CLUSTER_CONF_ID]->store(view.view, 0); - - const char *gap= (view.state_gap == true) ? "YES" : "NO"; - table->field[COLUMN_WSREP_STATUS_GAP]->store(gap, strlen(gap), - system_charset_info); - table->field[COLUMN_WSREP_STATUS_PROTO_VERSION]->store(view.proto_ver, 0); + ->store(view.state_id().seqno().get(), 0); + table->field[COLUMN_WSREP_STATUS_CLUSTER_CONF_ID] + ->store(view.view_seqno().get(), 0); + table->field[COLUMN_WSREP_STATUS_PROTO_VERSION] + ->store(view.protocol_version(), 0); if (schema_table_store_record(thd, table)) rc= 1; 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_common.sh b/scripts/wsrep_sst_common.sh index 5683b166163..321826b1975 100755 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -50,7 +50,7 @@ case "$1" in readonly WSREP_SST_OPT_HOST_UNESCAPED=$WSREP_SST_OPT_HOST ;; esac - remain=${WSREP_SST_OPT_ADDR#${WSREP_SST_OPT_HOST}} + remain=${WSREP_SST_OPT_ADDR#"${WSREP_SST_OPT_HOST}"} remain=${remain#:} readonly WSREP_SST_OPT_ADDR_PORT=${remain%%/*} remain=${remain#*/} diff --git a/scripts/wsrep_sst_mysqldump.sh b/scripts/wsrep_sst_mysqldump.sh index faa3f10639b..d36deb5759f 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 @@ -138,8 +139,8 @@ then # turned off for the session so that gtid state does not get altered while # the dump gets replayed on joiner. if [[ "$LOG_BIN" == 'ON' ]]; then - RESET_MASTER="RESET MASTER;" - SET_GTID_BINLOG_STATE="SET @@global.gtid_binlog_state='$GTID_BINLOG_STATE';" + RESET_MASTER="SET GLOBAL wsrep_on=OFF; RESET MASTER; SET GLOBAL wsrep_on=ON;" + SET_GTID_BINLOG_STATE="SET GLOBAL wsrep_on=OFF; SET @@global.gtid_binlog_state='$GTID_BINLOG_STATE'; SET GLOBAL wsrep_on=ON;" SQL_LOG_BIN_OFF="SET @@session.sql_log_bin=OFF;" fi fi diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 6417ee7f704..12fb9d3ba38 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -269,8 +269,9 @@ EOF cd $BINLOG_DIRNAME if ! [ -z $WSREP_SST_OPT_BINLOG_INDEX ] - binlog_files_full=$(tail -n $BINLOG_N_FILES ${BINLOG_FILENAME}.index) then + binlog_files_full=$(tail -n $BINLOG_N_FILES ${BINLOG_FILENAME}.index) + else cd $BINLOG_INDEX_DIRNAME binlog_files_full=$(tail -n $BINLOG_N_FILES ${BINLOG_INDEX_FILENAME}.index) fi @@ -508,9 +509,10 @@ EOF for ii in $(ls -1 ${BINLOG_FILENAME}.*) do if ! [ -z $WSREP_SST_OPT_BINLOG_INDEX ] - echo ${BINLOG_DIRNAME}/${ii} >> ${BINLOG_FILENAME}.index - then - echo ${BINLOG_DIRNAME}/${ii} >> ${BINLOG_INDEX_DIRNAME}/${BINLOG_INDEX_FILENAME}.index + then + echo ${BINLOG_DIRNAME}/${ii} >> ${BINLOG_FILENAME}.index + else + echo ${BINLOG_DIRNAME}/${ii} >> ${BINLOG_INDEX_DIRNAME}/${BINLOG_INDEX_FILENAME}.index fi done fi diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 697b794f39f..a22ce694805 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -16,21 +16,27 @@ IF(WITH_WSREP AND NOT EMBEDDED_LIBRARY) - SET(WSREP_INCLUDES ${CMAKE_SOURCE_DIR}/wsrep) SET(WSREP_SOURCES + wsrep_client_service.cc + wsrep_high_priority_service.cc + wsrep_server_service.cc + wsrep_storage_service.cc + wsrep_server_state.cc + 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_schema.cc + wsrep_plugin.cc + service_wsrep.cc ) - SET(WSREP_LIB wsrep) + SET(WSREP_LIB wsrep-lib wsrep_api_v26) ELSE() SET(WSREP_SOURCES wsrep_dummy.cc) ENDIF() @@ -42,7 +48,6 @@ ${PCRE_INCLUDES} ${ZLIB_INCLUDE_DIR} ${SSL_INCLUDE_DIRS} ${CMAKE_BINARY_DIR}/sql -${WSREP_INCLUDES} ) diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index db056a9f08e..6327cd138de 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -32,7 +32,9 @@ #include "event_db_repository.h" #include "sp_head.h" #include "sql_show.h" // append_definer, append_identifier - +#ifdef WITH_WSREP +#include "wsrep_trans_observer.h" +#endif /* WITH_WSREP */ /** @addtogroup Event_Scheduler @{ @@ -1353,6 +1355,10 @@ Event_job_data::execute(THD *thd, bool drop) thd->reset_for_next_command(); +#ifdef WITH_WSREP + wsrep_open(thd); + wsrep_before_command(thd); +#endif /* WITH_WSREP */ /* MySQL parser currently assumes that current database is either present in THD or all names in all statements are fully specified. @@ -1527,6 +1533,10 @@ end: if (save_sctx) event_sctx.restore_security_context(thd, save_sctx); #endif +#ifdef WITH_WSREP + wsrep_after_command_ignore_result(thd); + wsrep_close(thd); +#endif /* WITH_WSREP */ thd->lex->unit.cleanup(); thd->end_statement(); thd->cleanup_after_query(); diff --git a/sql/handler.cc b/sql/handler.cc index 001055cd475..1b5aaebe3cf 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -54,8 +54,12 @@ #include "semisync_master.h" #include "wsrep_mysqld.h" -#include "wsrep.h" +#ifdef WITH_WSREP +#include "wsrep_binlog.h" #include "wsrep_xid.h" +#include "wsrep_thd.h" +#include "wsrep_trans_observer.h" /* wsrep transaction hooks */ +#endif /* WITH_WSREP */ /* While we have legacy_db_type, we have this array to @@ -251,6 +255,9 @@ handlerton *ha_checktype(THD *thd, handlerton *hton, bool no_substitute) if (no_substitute) return NULL; +#ifdef WITH_WSREP + (void)wsrep_after_rollback(thd, false); +#endif /* WITH_WSREP */ return ha_default_handlerton(thd); } /* ha_checktype */ @@ -1199,17 +1206,28 @@ void trans_register_ha(THD *thd, bool all, handlerton *ht_arg) static int prepare_or_error(handlerton *ht, THD *thd, bool all) { + #ifdef WITH_WSREP + if (WSREP(thd) && ht->flags & HTON_WSREP_REPLICATION && + wsrep_before_prepare(thd, all)) + { + return(1); + } +#endif /* WITH_WSREP */ + int err= ht->prepare(ht, thd, all); status_var_increment(thd->status_var.ha_prepare_count); if (err) { - /* 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) -#endif my_error(ER_ERROR_DURING_COMMIT, MYF(0), err); } +#ifdef WITH_WSREP + if (WSREP(thd) && ht->flags & HTON_WSREP_REPLICATION && + wsrep_after_prepare(thd, all)) + { + err= 1; + } +#endif /* WITH_WSREP */ + return err; } @@ -1394,7 +1412,7 @@ int ha_commit_trans(THD *thd, bool all) } #ifdef WITH_ARIA_STORAGE_ENGINE - ha_maria::implicit_commit(thd, TRUE); + ha_maria::implicit_commit(thd, TRUE); #endif if (!ha_info) @@ -1404,6 +1422,12 @@ int ha_commit_trans(THD *thd, bool all) */ if (is_real_trans) thd->transaction.cleanup(); +#ifdef WITH_WSREP + if (WSREP(thd) && all && !error) + { + wsrep_commit_empty(thd, all); + } +#endif /* WITH_WSREP */ DBUG_RETURN(0); } @@ -1489,7 +1513,28 @@ int ha_commit_trans(THD *thd, bool all) if (trans->no_2pc || (rw_ha_count <= 1)) { +#ifdef WITH_WSREP + /* + This commit will not go through log_and_order() where wsrep commit + ordering is normally done. Commit ordering must be done here. + */ + bool run_wsrep_commit= (WSREP(thd) && + rw_ha_count && + wsrep_thd_is_local(thd) && + wsrep_has_changes(thd, all)); + if (run_wsrep_commit) + error= wsrep_before_commit(thd, all); + if (error) + { + ha_rollback_trans(thd, FALSE); + goto wsrep_err; + } +#endif /* WITH_WSREP */ error= ha_commit_one_phase(thd, all); +#ifdef WITH_WSREP + if (run_wsrep_commit) + error= wsrep_after_commit(thd, all); +#endif /* WITH_WSREP */ goto done; } @@ -1521,10 +1566,14 @@ int ha_commit_trans(THD *thd, bool all) DBUG_EXECUTE_IF("crash_commit_after_prepare", DBUG_SUICIDE();); #ifdef WITH_WSREP - if (!error && WSREP_ON && wsrep_is_wsrep_xid(&thd->transaction.xid_state.xid)) + if (!error && WSREP_ON) { - // xid was rewritten by wsrep - xid= wsrep_xid_seqno(thd->transaction.xid_state.xid); + wsrep::seqno const s= wsrep_xid_seqno(thd->wsrep_xid); + if (!s.is_undefined()) + { + // xid was rewritten by wsrep + xid= s.get(); + } } #endif /* WITH_WSREP */ @@ -1533,18 +1582,35 @@ int ha_commit_trans(THD *thd, bool all) error= commit_one_phase_2(thd, all, trans, is_real_trans); goto done; } - +#ifdef WITH_WSREP + if (wsrep_before_commit(thd, all)) + goto wsrep_err; +#endif /* WITH_WSREP */ DEBUG_SYNC(thd, "ha_commit_trans_before_log_and_order"); cookie= tc_log->log_and_order(thd, xid, all, need_prepare_ordered, need_commit_ordered); if (!cookie) + { + WSREP_DEBUG("log_and_order has failed %llu %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 || wsrep_after_commit(thd, all)) + { + mysql_mutex_lock(&thd->LOCK_thd_data); + if (thd->wsrep_trx().state() == wsrep::transaction::s_must_abort) + { + mysql_mutex_unlock(&thd->LOCK_thd_data); + (void)tc_log->unlog(cookie, xid); + goto wsrep_err; + } + mysql_mutex_unlock(&thd->LOCK_thd_data); + } +#endif /* WITH_WSREP */ DBUG_EXECUTE_IF("crash_commit_before_unlog", DBUG_SUICIDE();); if (tc_log->unlog(cookie, xid)) { @@ -1566,6 +1632,19 @@ done: goto end; /* Come here if error and we need to rollback. */ +#ifdef WITH_WSREP +wsrep_err: + mysql_mutex_lock(&thd->LOCK_thd_data); + if (thd->wsrep_trx().state() == wsrep::transaction::s_must_abort) + { + WSREP_DEBUG("BF abort has happened after prepare & certify"); + mysql_mutex_unlock(&thd->LOCK_thd_data); + ha_rollback_trans(thd, TRUE); + } + else + mysql_mutex_unlock(&thd->LOCK_thd_data); + +#endif /* WITH_WSREP */ err: error= 1; /* Transaction was rolled back */ /* @@ -1575,7 +1654,11 @@ err: */ if (!(thd->rgi_slave && thd->rgi_slave->is_parallel_exec)) ha_rollback_trans(thd, all); - + else + { + WSREP_DEBUG("rollback skipped %p %d",thd->rgi_slave, + thd->rgi_slave->is_parallel_exec); + } end: if (rw_trans && mdl_request.ticket) { @@ -1587,6 +1670,13 @@ end: */ thd->mdl_context.release_lock(mdl_request.ticket); } +#ifdef WITH_WSREP + if (WSREP(thd) && all && !error && (rw_ha_count == 0)) + { + wsrep_commit_empty(thd, all); + } +#endif /* WITH_WSREP */ + DBUG_RETURN(error); } @@ -1744,6 +1834,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 */ @@ -1759,9 +1852,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_trx().state(), + thd->query()); #endif /* WITH_WSREP */ } status_var_increment(thd->status_var.ha_rollback_count); @@ -1780,6 +1873,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 /* WITH_WSREP */ /* Always cleanup. Even if nht==0. There may be savepoints. */ if (is_real_trans) { @@ -1913,6 +2015,28 @@ static char* xid_to_str(char *buf, XID *xid) } #endif +#ifdef WITH_WSREP +static my_xid wsrep_order_and_check_continuity(XID *list, int len) +{ + wsrep_sort_xid_array(list, len); + wsrep::gtid cur_position= wsrep_get_SE_checkpoint(); + long long cur_seqno= cur_position.seqno().get(); + for (int i= 0; i < len; ++i) + { + if (!wsrep_is_wsrep_xid(list + i) || + wsrep_xid_seqno(list + i) != cur_seqno + 1) + { + WSREP_WARN("Discovered discontinuity in recovered wsrep " + "transaction XIDs. Truncating the recovery list to " + "%d entries", i); + break; + } + ++cur_seqno; + } + WSREP_INFO("Last wsrep seqno to be recovered %lld", cur_seqno); + return (cur_seqno < 0 ? 0 : cur_seqno); +} +#endif /* WITH_WSREP */ /** recover() step of xa. @@ -1950,10 +2074,32 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin, { sql_print_information("Found %d prepared transaction(s) in %s", got, hton_name(hton)->str); +#ifdef WITH_WSREP + /* If wsrep_on=ON, XIDs are first ordered and then the range of + recovered XIDs is checked for continuity. All the XIDs which + are in continuous range can be safely committed if binlog + is off since they have already ordered and certified in the + cluster. + + The discontinuity of wsrep XIDs may happen because the GTID + is assigned for transaction in wsrep_before_prepare(), but the + commit order is entered in wsrep_before_commit(). This means that + transactions may run prepare step out of order and may + result in gap in wsrep XIDs. This can be the case for example + if we have T1 with seqno 1 and T2 with seqno 2 and the server + crashes after T2 finishes prepare step but before T1 starts + the prepare. + */ + my_xid wsrep_limit= 0; + if (WSREP_ON) + { + wsrep_limit= wsrep_order_and_check_continuity(info->list, got); + } +#endif /* WITH_WSREP */ for (int i=0; i < got; i ++) { my_xid x= IF_WSREP(WSREP_ON && wsrep_is_wsrep_xid(&info->list[i]) ? - wsrep_xid_seqno(info->list[i]) : + wsrep_xid_seqno(&info->list[i]) : info->list[i].get_my_xid(), info->list[i].get_my_xid()); if (!x) // not "mine" - that is generated by external TM @@ -1972,9 +2118,12 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin, continue; } // recovery mode - if (info->commit_list ? - my_hash_search(info->commit_list, (uchar *)&x, sizeof(x)) != 0 : - tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT) + if (IF_WSREP((wsrep_emulate_bin_log && + wsrep_is_wsrep_xid(info->list + i) && + x <= wsrep_limit), false) || + (info->commit_list ? + my_hash_search(info->commit_list, (uchar *)&x, sizeof(x)) != 0 : + tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)) { #ifndef DBUG_OFF int rc= @@ -2332,11 +2481,26 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv) { int err; handlerton *ht= ha_info->ht(); +#ifdef WITH_WSREP + if (WSREP(thd) && ht->flags & HTON_WSREP_REPLICATION) + { + 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); error=1; } +#ifdef WITH_WSREP + if (WSREP(thd) && ht->flags & HTON_WSREP_REPLICATION) + { + WSREP_DEBUG("ha_rollback_to_savepoint: run after_rollback hook"); + (void) wsrep_after_rollback(thd, !thd->in_sub_stmt); + } +#endif // WITH_WSREP status_var_increment(thd->status_var.ha_rollback_count); ha_info_next= ha_info->next(); ha_info->reset(); /* keep it conveniently zero-filled */ @@ -2353,6 +2517,16 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv) */ int ha_savepoint(THD *thd, SAVEPOINT *sv) { +#ifdef WITH_WSREP + /* + Register binlog hton for savepoint processing if wsrep binlog + emulation is on. + */ + if (WSREP_EMULATE_BINLOG(thd) && wsrep_thd_is_local(thd)) + { + wsrep_register_binlog_handler(thd, thd->in_multi_stmt_transaction_mode()); + } +#endif /* WITH_WSREP */ int error=0; THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt : &thd->transaction.all); @@ -5968,6 +6142,12 @@ bool handler::check_table_binlog_row_based(bool binlog_row) return false; if (unlikely((table->in_use->variables.sql_log_bin_off))) return 0; /* Called by partitioning engine */ +#ifdef WITH_WSREP + if (!table->in_use->variables.sql_log_bin && + wsrep_thd_is_applying(table->in_use)) + return 0; /* wsrep patch sets sql_log_bin to silence binlogging + from high priority threads */ +#endif /* WITH_WSREP */ if (unlikely((!check_table_binlog_row_based_done))) { check_table_binlog_row_based_done= 1; @@ -5998,12 +6178,12 @@ bool handler::check_table_binlog_row_based_internal(bool binlog_row) Otherwise, return 'true' if binary logging is on. */ IF_WSREP(((WSREP_EMULATE_BINLOG(thd) && - (thd->wsrep_exec_mode != REPL_RECV)) || + wsrep_thd_is_local(thd)) || ((WSREP(thd) || (thd->variables.option_bits & OPTION_BIN_LOG)) && mysql_bin_log.is_open())), - (thd->variables.option_bits & OPTION_BIN_LOG) && - mysql_bin_log.is_open())); + (thd->variables.option_bits & OPTION_BIN_LOG) && + mysql_bin_log.is_open())); } @@ -6128,23 +6308,9 @@ int binlog_log_row(TABLE* table, const uchar *before_record, /* only InnoDB tables will be replicated through binlog emulation */ if ((WSREP_EMULATE_BINLOG(thd) && - table->file->partition_ht()->db_type != DB_TYPE_INNODB) || - (thd->wsrep_ignore_table == true)) + !(table->file->partition_ht()->flags & HTON_WSREP_REPLICATION)) || + 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)) @@ -6256,6 +6422,27 @@ 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 && + wsrep_thd_is_local(thd) && + 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)) + { + DBUG_RETURN(ER_LOCK_DEADLOCK); + } + DBUG_RETURN(0); +} +#endif /* WITH_WSREP */ int handler::ha_write_row(uchar *buf) { @@ -6278,7 +6465,15 @@ int handler::ha_write_row(uchar *buf) { rows_changed++; error= binlog_log_row(table, 0, buf, log_func); +#ifdef WITH_WSREP + if (table_share->tmp_table == NO_TMP_TABLE && + WSREP(ha_thd()) && (error= wsrep_after_row(ha_thd()))) + { + DBUG_RETURN(error); + } +#endif /* WITH_WSREP */ } + DEBUG_SYNC_C("ha_write_row_end"); DBUG_RETURN(error); } @@ -6310,6 +6505,13 @@ 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 + if (table_share->tmp_table == NO_TMP_TABLE && + WSREP(ha_thd()) && (error= wsrep_after_row(ha_thd()))) + { + return error; + } +#endif /* WITH_WSREP */ } return error; } @@ -6365,6 +6567,13 @@ int handler::ha_delete_row(const uchar *buf) { rows_changed++; error= binlog_log_row(table, buf, 0, log_func); +#ifdef WITH_WSREP + if (table_share->tmp_table == NO_TMP_TABLE && + WSREP(ha_thd()) && (error= wsrep_after_row(ha_thd()))) + { + return error; + } +#endif /* WITH_WSREP */ } return error; } @@ -6554,7 +6763,7 @@ int ha_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal) DBUG_ENTER("ha_abort_transaction"); if (!WSREP(bf_thd) && !(bf_thd->variables.wsrep_OSU_method == WSREP_OSU_RSU && - bf_thd->wsrep_exec_mode == TOTAL_ORDER)) { + wsrep_thd_is_toi(bf_thd))) { DBUG_RETURN(0); } @@ -6570,54 +6779,6 @@ 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) - { - WSREP_DEBUG("fake trx id skipped: %" PRIu64, 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."); - - DBUG_VOID_RETURN; -} #endif /* WITH_WSREP */ diff --git a/sql/handler.h b/sql/handler.h index fc6246c38a1..f5a7051a4e2 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1485,7 +1485,6 @@ struct handlerton THD *victim_thd, my_bool signal); int (*set_checkpoint)(handlerton *hton, const XID* xid); int (*get_checkpoint)(handlerton *hton, XID* xid); - void (*fake_trx_id)(handlerton *hton, THD *thd); /* Optional clauses in the CREATE/ALTER TABLE */ @@ -1682,6 +1681,9 @@ handlerton *ha_default_tmp_handlerton(THD *thd); // Engine needs to access the main connect string in partitions #define HTON_CAN_READ_CONNECT_STRING_IN_PARTITION (1 <<12) +/* can be replicated by wsrep replication provider plugin */ +#define HTON_WSREP_REPLICATION (1 << 13) + class Ha_trx_info; struct THD_TRANS @@ -4837,9 +4839,6 @@ int ha_savepoint(THD *thd, SAVEPOINT *sv); int ha_release_savepoint(THD *thd, SAVEPOINT *sv); #ifdef WITH_WSREP int ha_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal); -void ha_fake_trx_id(THD *thd); -#else -inline void ha_fake_trx_id(THD *thd) { } #endif /* these are called by storage engines */ diff --git a/sql/item_create.cc b/sql/item_create.cc index 87bf69f3c96..ba7a704e29b 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 @@ -6905,6 +6944,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) +{ + 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) +{ + 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; + } + thd->lex->safe_to_cache_query= 0; + return func; +} +#endif /* WITH_WSREP */ #ifdef HAVE_SPATIAL Create_func_x Create_func_x::s_singleton; @@ -7347,6 +7443,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)}, +#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_func.cc b/sql/item_func.cc index c73cfc7953a..a10f381b1dc 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2451,7 +2451,7 @@ void Item_func_rand::seed_random(Item *arg) THD *thd= current_thd; if (WSREP(thd)) { - if (thd->wsrep_exec_mode==REPL_RECV) + if (wsrep_thd_is_applying(thd)) tmp= thd->wsrep_rand; else tmp= thd->wsrep_rand= (uint32) arg->val_int(); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 8cc539f3d12..77e870b297d 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -5264,3 +5264,102 @@ 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 gtid= current_thd->wsrep_cs().last_written_gtid(); + if (gtid_str.alloc(wsrep::gtid_c_str_len())) + { + my_error(ER_OUTOFMEMORY, wsrep::gtid_c_str_len()); + null_value= true; + return NULL; + } + + ssize_t gtid_len= gtid_print_to_c_str(gtid, (char*) gtid_str.ptr(), + wsrep::gtid_c_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) +{ + /* TODO: Should call Wsrep_server_state.instance().last_committed_gtid() + instead. */ + wsrep::gtid gtid= Wsrep_server_state::instance().provider().last_committed_gtid(); + if (gtid_str.alloc(wsrep::gtid_c_str_len())) + { + my_error(ER_OUTOFMEMORY, wsrep::gtid_c_str_len()); + null_value= true; + return NULL; + } + ssize_t gtid_len= wsrep::gtid_print_to_c_str(gtid, (char*) gtid_str.ptr(), + wsrep::gtid_c_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; + } + + enum wsrep::provider::status status= + wsrep_sync_wait_upto(current_thd, >id, timeout); + + if (status) + { + int err; + switch (status) { + case wsrep::provider::error_transaction_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 762a3c2559e..2ead0f44e49 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -1804,5 +1804,56 @@ public: Item *get_copy(THD *thd) { return get_item_copy<Item_temptable_rowid>(thd, this); } }; +#ifdef WITH_WSREP + +#include "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 1564059bb20..c1140eddaae 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -1100,20 +1100,16 @@ void Global_read_lock::unlock_global_read_lock(THD *thd) #ifdef WITH_WSREP if (m_state == GRL_ACQUIRED_AND_BLOCKS_COMMIT) { - if (WSREP(thd) || wsrep_node_is_donor()) + Wsrep_server_state& server_state= Wsrep_server_state::instance(); + if (server_state.state() == Wsrep_server_state::s_donor) { + /* TODO: maybe redundant here?: */ wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; - wsrep->resume(wsrep); - /* resync here only if we did implicit desync earlier */ - if (!wsrep_desync && wsrep_node_is_synced()) - { - int ret = wsrep->resync(wsrep); - if (ret != WSREP_OK) - { - WSREP_WARN("resync failed %d for FTWRL: db: %s, query: %s", - ret, thd->get_db(), thd->query()); - } - } + server_state.resume(); + } + else if (WSREP(thd)) + { + server_state.resume_and_resync(); } } #endif /* WITH_WSREP */ @@ -1159,62 +1155,30 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd) m_state= GRL_ACQUIRED_AND_BLOCKS_COMMIT; #ifdef WITH_WSREP + /* Native threads should bail out before wsrep oprations to follow. - Donor servicing thread is an exception, it should pause provider but not desync, - as it is already desynced in donor state + Donor servicing thread is an exception, it should pause provider + but not desync, as it is already desynced in donor state */ - if (!WSREP(thd) && !wsrep_node_is_donor()) + Wsrep_server_state& server_state= Wsrep_server_state::instance(); + if (!WSREP(thd) && server_state.state() != Wsrep_server_state::s_donor) { DBUG_RETURN(FALSE); } - /* if already desynced or donor, avoid double desyncing - if not in PC and synced, desyncing is not possible either - */ - if (wsrep_desync || !wsrep_node_is_synced()) + wsrep::seqno paused_seqno; + if (server_state.state() == Wsrep_server_state::s_donor) { - WSREP_DEBUG("desync set upfont, skipping implicit desync for FTWRL: %d", - wsrep_desync); + paused_seqno= server_state.pause(); } else { - int rcode; - WSREP_DEBUG("running implicit desync for node"); - rcode = wsrep->desync(wsrep); - if (rcode != WSREP_OK) - { - WSREP_WARN("FTWRL desync failed %d for schema: %s, query: %s", - rcode, thd->get_db(), thd->query()); - my_message(ER_LOCK_DEADLOCK, "wsrep desync failed for FTWRL", MYF(0)); - DBUG_RETURN(TRUE); - } - } - - long long ret = wsrep->pause(wsrep); - if (ret >= 0) - { - wsrep_locked_seqno= ret; + paused_seqno= server_state.desync_and_pause(); } - else if (ret != -ENOSYS) /* -ENOSYS - no provider */ + WSREP_INFO("Server paused at: %lld", paused_seqno.get()); + if (paused_seqno.get() >= 0) { - 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)); - - /* - For some reason Galera wants to crash here in debug build. - It is equivalent of original assertion. - */ - DBUG_ASSERT(0); - wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; - my_error(ER_LOCK_DEADLOCK, MYF(0)); - DBUG_RETURN(TRUE); - } + wsrep_locked_seqno= paused_seqno.get(); } #endif /* WITH_WSREP */ DBUG_RETURN(FALSE); diff --git a/sql/log.cc b/sql/log.cc index a56117a4ac1..68e34513d40 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -55,10 +55,14 @@ #include "sql_show.h" #include "my_pthread.h" #include "semisync_master.h" -#include "wsrep_mysqld.h" #include "sp_rcontext.h" #include "sp_head.h" +#include "wsrep_mysqld.h" +#ifdef WITH_WSREP +#include "wsrep_trans_observer.h" +#endif /* WITH_WSREP */ + /* max size of the log message */ #define MAX_LOG_BUFFER_SIZE 1024 #define MAX_TIME_SIZE 32 @@ -1703,7 +1707,7 @@ 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= cache_mngr->get_binlog_cache_log(true); uchar *buf; size_t len=0; wsrep_write_cache_buf(cache, &buf, &len); @@ -2297,8 +2301,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_trx().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); @@ -5970,7 +5983,9 @@ MYSQL_BIN_LOG::write_gtid_event(THD *thd, bool standalone, DBUG_PRINT("enter", ("standalone: %d", standalone)); #ifdef WITH_WSREP - if (WSREP(thd) && thd->wsrep_trx_meta.gtid.seqno != -1 && wsrep_gtid_mode && !thd->variables.gtid_seq_no) + if (WSREP(thd) && + (wsrep_thd_trx_seqno(thd) > 0) && + wsrep_gtid_mode && !thd->variables.gtid_seq_no) { domain_id= wsrep_gtid_domain_id; } else { @@ -6287,7 +6302,7 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate) */ /* applier and replayer can skip writing binlog events */ if ((WSREP_EMULATE_BINLOG(thd) && - IF_WSREP(thd->wsrep_exec_mode != REPL_RECV, 0)) || is_open()) + IF_WSREP(thd->wsrep_cs().mode() == wsrep::client_state::m_local, 0)) || is_open()) { my_off_t UNINIT_VAR(my_org_b_tell); #ifdef HAVE_REPLICATION @@ -7670,7 +7685,11 @@ bool MYSQL_BIN_LOG::write_transaction_to_binlog_events(group_commit_entry *entry) { int is_leader= queue_for_group_commit(entry); - +#ifdef WITH_WSREP + if (is_leader >= 0 && + wsrep_ordered_commit(entry->thd, entry->all, wsrep_apply_error())) + return true; +#endif /* WITH_WSREP */ /* The first in the queue handles group commit for all; the others just wait to be signalled when group commit is done. @@ -10592,7 +10611,10 @@ 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" + +IO_CACHE *wsrep_get_trans_cache(THD * thd) { DBUG_ASSERT(binlog_hton->slot != HA_SLOT_UNDEF); binlog_cache_mngr *cache_mngr = (binlog_cache_mngr*) @@ -10605,17 +10627,10 @@ IO_CACHE * get_trans_log(THD * thd) return NULL; } - -bool wsrep_trans_cache_is_empty(THD *thd) -{ - binlog_cache_mngr *const cache_mngr= - (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); - return (!cache_mngr || cache_mngr->trx_cache.empty()); -} - - -void thd_binlog_trx_reset(THD * thd) +void wsrep_thd_binlog_trx_reset(THD * thd) { + DBUG_ENTER("wsrep_thd_binlog_trx_reset"); + WSREP_DEBUG("wsrep_thd_binlog_reset"); /* todo: fix autocommit select to not call the caller */ @@ -10634,6 +10649,7 @@ void thd_binlog_trx_reset(THD * thd) } } thd->clear_binlog_table_maps(); + DBUG_VOID_RETURN; } @@ -10646,4 +10662,78 @@ void thd_binlog_rollback_stmt(THD * thd) if (cache_mngr) cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF); } + +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_sr().fragments_certified() > 0 && + (trx_cache->get_prev_position() == MY_OFF_T_UNDEF || + trx_cache->get_prev_position() < thd->wsrep_sr().bytes_certified())) + { + WSREP_DEBUG("statement rollback is not safe for streaming replication" + " pre-stmt_pos: %llu, frag repl pos: %lu\n" + "Thread: %llu, SQL: %s", + trx_cache->get_prev_position(), + thd->wsrep_sr().bytes_certified(), + 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..42fcfcc3ab6 100644 --- a/sql/log.h +++ b/sql/log.h @@ -18,7 +18,6 @@ #define LOG_H #include "handler.h" /* my_xid */ -#include "wsrep.h" #include "wsrep_mysqld.h" #include "rpl_constants.h" @@ -1212,6 +1211,10 @@ static inline TC_LOG *get_tc_log_implementation() return &tc_log_mmap; } +#ifdef WITH_WSREP +IO_CACHE* wsrep_get_trans_cache(THD *); +void wsrep_thd_binlog_trx_reset(THD * thd); +#endif /* WITH_WSREP */ class Gtid_list_log_event; const char * diff --git a/sql/log_event.cc b/sql/log_event.cc index 7a0d0beb5ad..ed2b25929e4 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -5780,6 +5780,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 */ } /* @@ -11287,13 +11295,13 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) { WSREP_WARN("BF applier failed to open_and_lock_tables: %u, fatal: %d " "wsrep = (exec_mode: %d conflict_state: %d seqno: %lld)", - thd->get_stmt_da()->sql_errno(), - thd->is_fatal_error, - thd->wsrep_exec_mode, - thd->wsrep_conflict_state, - (long long)wsrep_thd_trx_seqno(thd)); + thd->get_stmt_da()->sql_errno(), + thd->is_fatal_error, + thd->wsrep_cs().mode(), + thd->wsrep_trx().state(), + (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)) { @@ -11430,10 +11438,10 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) #ifdef HAVE_QUERY_CACHE #ifdef WITH_WSREP /* - Moved invalidation right before the call to rows_event_stmt_cleanup(), - to avoid query cache being polluted with stale entries. + Moved invalidation right before the call to rows_event_stmt_cleanup(), + to avoid query cache being polluted with stale entries, */ - if (! (WSREP(thd) && (thd->wsrep_exec_mode == REPL_RECV))) + if (! (WSREP(thd) && wsrep_thd_is_applying(thd))) { #endif /* WITH_WSREP */ query_cache.invalidate_locked_for_write(thd, rgi->tables_to_lock); @@ -11546,6 +11554,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) @@ -11633,7 +11648,7 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) restore_empty_query_table_list(thd->lex); #if defined(WITH_WSREP) && defined(HAVE_QUERY_CACHE) - if (WSREP(thd) && thd->wsrep_exec_mode == REPL_RECV) + if (WSREP(thd) && wsrep_thd_is_applying(thd)) { query_cache.invalidate_locked_for_write(thd, rgi->tables_to_lock); } diff --git a/sql/mdl.cc b/sql/mdl.cc index 19468a124c6..ccd7a71e9f4 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -24,9 +24,6 @@ #include <mysql/plugin.h> #include <mysql/service_thd_wait.h> #include <mysql/psi/mysql_stage.h> -#include "wsrep_mysqld.h" -#include "wsrep_thd.h" - #ifdef HAVE_PSI_INTERFACE static PSI_mutex_key key_MDL_wait_LOCK_wait_status; @@ -1218,10 +1215,9 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket) wsrep_thd_is_BF(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; @@ -1240,20 +1236,8 @@ 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"); - } - } - } + if (!added) + m_list.push_back(ticket); } else #endif /* WITH_WSREP */ @@ -1709,6 +1693,12 @@ MDL_lock::MDL_backup_lock::m_waiting_incompatible[MDL_BACKUP_END]= Check if request for the metadata lock can be satisfied given its current state. + New lock request can be satisfied iff: + - There are no incompatible types of satisfied requests + in other contexts + - There are no waiting requests which have higher priority + than this request when priority was not ignored. + @param type_arg The requested lock type. @param requestor_ctx The MDL context of the requestor. @param ignore_lock_priority Ignore lock priority. @@ -1726,78 +1716,72 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg, MDL_context *requestor_ctx, bool ignore_lock_priority) const { - 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; +#ifdef WITH_WSREP /* - New lock request can be satisfied iff: - - There are no incompatible types of satisfied requests - in other contexts - - There are no waiting requests which have higher priority - than this request when priority was not ignored. + Approve lock request in BACKUP namespace for BF threads. + We should get rid of this code and forbid FTWRL/BACKUP statements + when wsrep is active. */ - if (ignore_lock_priority || !(m_waiting.bitmap() & waiting_incompat_map)) + if ((wsrep_thd_is_toi(requestor_ctx->get_thd()) || + wsrep_thd_is_applying(requestor_ctx->get_thd())) && + key.mdl_namespace() == MDL_key::BACKUP) { - if (! (m_granted.bitmap() & granted_incompat_map)) - can_grant= TRUE; - else + bool waiting_incompatible= m_waiting.bitmap() & waiting_incompat_map; + bool granted_incompatible= m_granted.bitmap() & granted_incompat_map; + if (waiting_incompatible || granted_incompatible) { - Ticket_iterator it(m_granted); - MDL_ticket *ticket; + WSREP_DEBUG("global lock granted for BF%s: %lu %s", + waiting_incompatible ? " (waiting queue)" : "", + thd_get_thread_id(requestor_ctx->get_thd()), + wsrep_thd_query(requestor_ctx->get_thd())); + } + return true; + } +#endif /* WITH_WSREP */ - /* Check that the incompatible lock belongs to some other context. */ - while ((ticket= it++)) + if (!ignore_lock_priority && (m_waiting.bitmap() & waiting_incompat_map)) + return false; + + if (m_granted.bitmap() & granted_incompat_map) + { + Ticket_iterator it(m_granted); + bool can_grant= true; + + /* Check that the incompatible lock belongs to some other context. */ + while (auto ticket= it++) + { + if (ticket->get_ctx() != requestor_ctx && + ticket->is_incompatible_when_granted(type_arg)) { - if (ticket->get_ctx() != requestor_ctx && - ticket->is_incompatible_when_granted(type_arg)) - { + can_grant= false; #ifdef WITH_WSREP - if (wsrep_thd_is_BF(requestor_ctx->get_thd(),false) && - key.mdl_namespace() == MDL_key::BACKUP) - { - 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)) + /* + non WSREP threads must report conflict immediately + note: RSU processing wsrep threads, have wsrep_on==OFF + */ + if (WSREP(requestor_ctx->get_thd()) || + requestor_ctx->get_thd()->wsrep_cs().mode() == + wsrep::client_state::m_rsu) + { + wsrep_handle_mdl_conflict(requestor_ctx, ticket, &key); + if (wsrep_log_conflicts) { - wsrep_can_grant= FALSE; - if (wsrep_log_conflicts) - { - MDL_lock * lock = ticket->get_lock(); - WSREP_INFO( - "MDL conflict db=%s table=%s ticket=%d solved by %s", - lock->key.db_name(), lock->key.name(), ticket->get_type(), - "abort" ); - } + auto key= ticket->get_key(); + WSREP_INFO("MDL conflict db=%s table=%s ticket=%d solved by abort", + key->db_name(), key->name(), ticket->get_type()); } - else - can_grant= TRUE; - /* Continue loop */ -#else - break; -#endif /* WITH_WSREP */ + continue; } +#endif /* WITH_WSREP */ + break; } - if ((ticket == NULL) && wsrep_can_grant) - can_grant= TRUE; /* Incompatible locks are our own. */ - } - } - else - { - if (wsrep_thd_is_BF(requestor_ctx->get_thd(), false) && - key.mdl_namespace() == MDL_key::BACKUP) - { - WSREP_DEBUG("global lock granted for BF (waiting queue): %lu %s", - thd_get_thread_id(requestor_ctx->get_thd()), - wsrep_thd_query(requestor_ctx->get_thd())); - can_grant = true; } + return can_grant; } - return can_grant; + return true; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a7e29811dd1..216b5d1c622 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -72,8 +72,10 @@ #include "debug_sync.h" #include "wsrep_mysqld.h" #include "wsrep_var.h" +#ifdef WITH_WSREP #include "wsrep_thd.h" #include "wsrep_sst.h" +#endif /* WITH_WSREP */ #include "proxy_protocol.h" #include "sql_callback.h" @@ -1599,7 +1601,7 @@ static void close_connections(void) error= mysql_cond_timedwait(&COND_start_thread, &LOCK_start_thread, &abstime); if (error != EINTR) - break; + break; } #ifdef EXTRA_DEBUG if (error != 0 && error != ETIMEDOUT && !count++) @@ -1661,11 +1663,12 @@ static void close_connections(void) #ifdef WITH_WSREP /* skip wsrep system threads as well */ - if (WSREP(tmp) && (tmp->wsrep_exec_mode==REPL_RECV || tmp->wsrep_applier)) + if (WSREP(tmp) && (wsrep_thd_is_applying(tmp) || tmp->wsrep_applier)) continue; #endif tmp->set_killed(KILL_SERVER_HARD); MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp)); + if (WSREP(tmp)) mysql_mutex_lock(&tmp->LOCK_thd_data); mysql_mutex_lock(&tmp->LOCK_thd_kill); if (tmp->mysys_var) { @@ -1690,6 +1693,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_thd_data); } mysql_mutex_unlock(&LOCK_thread_count); // For unlink from list @@ -1759,7 +1763,7 @@ static void close_connections(void) * The code here makes sure mysqld will not hang during shutdown * even if wsrep provider has problems in shutting down. */ - if (WSREP(tmp) && tmp->wsrep_exec_mode==REPL_RECV) + if (WSREP(tmp) && wsrep_thd_is_applying(tmp)) { sql_print_information("closing wsrep system thread"); tmp->set_killed(KILL_CONNECTION); @@ -1782,6 +1786,12 @@ 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); @@ -1936,17 +1946,16 @@ static void kill_server(int sig) else sql_print_error(ER_DEFAULT(ER_GOT_SIGNAL),my_progname,sig); /* purecov: inspected */ +#ifdef WITH_WSREP /* Stop wsrep threads in case they are running. */ if (wsrep_running_threads > 0) { - wsrep_stop_replication(NULL); + wsrep_shutdown_replication(); } +#endif close_connections(); - if (wsrep_inited == 1) - wsrep_deinit(true); - if (sig != MYSQL_KILL_SIGNAL && sig != 0) unireg_abort(1); /* purecov: inspected */ @@ -2028,8 +2037,8 @@ extern "C" void unireg_abort(int exit_code) disable_log_notes= 1; #ifdef WITH_WSREP - /* Check if wsrep class is used. If yes, then cleanup wsrep */ - if (wsrep) + if (WSREP_ON && + Wsrep_server_state::instance().state() != wsrep::server_state::s_disconnected) { /* This is an abort situation, we cannot expect to gracefully close all @@ -2037,15 +2046,19 @@ extern "C" void unireg_abort(int exit_code) */ wsrep_close_client_connections(FALSE); shutdown_in_progress= 1; - wsrep->disconnect(wsrep); + Wsrep_server_state::instance().disconnect(); WSREP_INFO("Service disconnected."); wsrep_close_threads(NULL); /* this won't close all threads */ sleep(1); /* so give some time to exit for those which can */ WSREP_INFO("Some threads may fail to exit."); - + } + if (WSREP_ON) + { /* In bootstrap mode we deinitialize wsrep here. */ - if (opt_bootstrap && wsrep_inited) - wsrep_deinit(true); + if (opt_bootstrap || wsrep_recovery) + { + if (wsrep_inited) wsrep_deinit(true); + } } #endif // WITH_WSREP @@ -2073,6 +2086,9 @@ static void mysqld_exit(int exit_code) rpl_deinit_gtid_waiting(); rpl_deinit_gtid_slave_state(); wait_for_signal_thread_to_end(); +#ifdef WITH_WSREP + wsrep_deinit_server(); +#endif /* WITH_WSREP */ mysql_audit_finalize(); clean_up_mutexes(); clean_up_error_log_mutex(); @@ -2309,9 +2325,6 @@ static void clean_up_mutexes() ****************************************************************************/ #ifdef EMBEDDED_LIBRARY -static void set_ports() -{ -} void close_connection(THD *thd, uint sql_errno) { } @@ -2805,12 +2818,14 @@ void unlink_thd(THD *thd) thd->add_status_to_global(); unlink_not_visible_thd(thd); +#ifdef WITH_WSREP /* Do not decrement when its wsrep system thread. wsrep_applier is set for applier as well as rollbacker threads. */ - if (IF_WSREP(!thd->wsrep_applier, 1)) - dec_connection_count(thd->scheduler); + if (!thd->wsrep_applier) +#endif /* WITH_WSREP */ + dec_connection_count(thd->scheduler); thd->free_connection(); @@ -5239,7 +5254,9 @@ static int init_server_components() wsrep_thr_init(); #endif - if (WSREP_ON && !wsrep_recovery && !opt_abort) /* WSREP BEFORE SE */ +#ifdef WITH_WSREP + if (wsrep_init_server()) unireg_abort(1); + if (WSREP_ON && !wsrep_recovery && !opt_abort) { if (opt_bootstrap) // bootsrap option given - disable wsrep functionality { @@ -5272,6 +5289,7 @@ static int init_server_components() } } } +#endif /* WITH_WSREP */ if (opt_bin_log) { @@ -5848,8 +5866,7 @@ int mysqld_main(int argc, char **argv) set_user(mysqld_user, user_info); } - if (WSREP_ON && wsrep_check_opts()) - global_system_variables.wsrep_on= 0; + if (WSREP_ON && wsrep_check_opts()) unireg_abort(1); /* The subsequent calls may take a long time : e.g. innodb log read. @@ -5949,24 +5966,11 @@ int mysqld_main(int argc, char **argv) } else { - wsrep_SE_initialized(); - - if (wsrep_before_SE()) - { - /*! in case of no SST wsrep waits in view handler callback */ - 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."); - } - } - else + wsrep_init_globals(); + if (!wsrep_before_SE()) { wsrep_init_startup (false); } - wsrep_create_appliers(wsrep_slave_threads - 1); } } @@ -8096,6 +8100,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} @@ -9558,7 +9576,9 @@ void refresh_status(THD *thd) reset_status_vars(); #ifdef WITH_WSREP if (WSREP_ON) - wsrep->stats_reset(wsrep); + { + Wsrep_server_state::instance().provider().reset_status(); + } #endif /* WITH_WSREP */ /* Reset the counters of all key caches (default and named). */ diff --git a/sql/protocol.cc b/sql/protocol.cc index 7eee9283989..38eb8ac99f7 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -551,8 +551,26 @@ 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)); +#ifdef WITH_WSREP + /* + Commented out: This sanity check does not hold in general. + Thd->LOCK_thd_data() 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 + */ + DBUG_ASSERT(thd->wsrep_trx().state() != wsrep::transaction::s_replaying); + if (WSREP(thd) && thd->wsrep_trx().state() == + wsrep::transaction::s_replaying) + { + WSREP_ERROR("attempting net_end_statement while replaying"); + return; + } +#endif /* WITH_WSREP */ + DBUG_ENTER("Protocol::end_statement"); DBUG_ASSERT(! thd->get_stmt_da()->is_sent()); bool error= FALSE; diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index 94c1f08e4e3..84661fa513d 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -329,6 +329,7 @@ unpack_row(rpl_group_info *rgi, (int) (pack_ptr - old_pack_ptr))); if (!pack_ptr) { +#ifdef WITH_WSREP if (WSREP_ON) { /* @@ -344,7 +345,7 @@ unpack_row(rpl_group_info *rgi, (table_found) ? "found" : "not found", row_end ); } - +#endif /* WITH_WSREP */ rgi->rli->report(ERROR_LEVEL, ER_SLAVE_CORRUPT_EVENT, rgi->gtid_info(), "Could not read field '%s' of table '%s.%s'", diff --git a/sql/service_wsrep.cc b/sql/service_wsrep.cc new file mode 100644 index 00000000000..f4cf49b9b84 --- /dev/null +++ b/sql/service_wsrep.cc @@ -0,0 +1,255 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "mariadb.h" + +#include "mysql/service_wsrep.h" +#include "wsrep/key.hpp" +#include "wsrep_thd.h" +#include "wsrep_trans_observer.h" +#include "sql_class.h" +#include "debug_sync.h" + +extern "C" my_bool wsrep_on(const THD *thd) +{ + return my_bool(WSREP(thd)); +} + +extern "C" void wsrep_thd_LOCK(const THD *thd) +{ + mysql_mutex_lock(&thd->LOCK_thd_data); +} + +extern "C" void wsrep_thd_UNLOCK(const THD *thd) +{ + mysql_mutex_unlock(&thd->LOCK_thd_data); +} + +extern "C" const char* wsrep_thd_client_state_str(const THD *thd) +{ + return wsrep::to_c_string(thd->wsrep_cs().state()); +} + +extern "C" const char* wsrep_thd_client_mode_str(const THD *thd) +{ + return wsrep::to_c_string(thd->wsrep_cs().mode()); +} + +extern "C" const char* wsrep_thd_transaction_state_str(const THD *thd) +{ + return wsrep::to_c_string(thd->wsrep_cs().transaction().state()); +} + + +extern "C" const char *wsrep_thd_query(const THD *thd) +{ + return thd ? thd->query() : NULL; +} + +extern "C" query_id_t wsrep_thd_transaction_id(const THD *thd) +{ + return thd->wsrep_cs().transaction().id().get(); +} + +extern "C" long long wsrep_thd_trx_seqno(const THD *thd) +{ + const wsrep::client_state& cs= thd->wsrep_cs(); + if (cs.mode() == wsrep::client_state::m_toi) + { + return cs.toi_meta().seqno().get(); + } + else + { + return cs.transaction().ws_meta().seqno().get(); + } +} + +extern "C" void wsrep_thd_self_abort(THD *thd) +{ + thd->wsrep_cs().bf_abort(wsrep::seqno(0)); +} + +extern "C" const char* wsrep_get_sr_table_name() +{ + return wsrep_sr_table_name_full; +} + +extern "C" my_bool wsrep_get_debug() +{ + return wsrep_debug; +} + +extern "C" my_bool wsrep_thd_is_local(const THD *thd) +{ + return thd->wsrep_cs().mode() == wsrep::client_state::m_local; +} + +extern "C" my_bool wsrep_thd_is_applying(const THD *thd) +{ + return thd->wsrep_cs().mode() == wsrep::client_state::m_high_priority; +} + +extern "C" my_bool wsrep_thd_is_toi(const THD *thd) +{ + return thd->wsrep_cs().mode() == wsrep::client_state::m_toi; +} + +extern "C" my_bool wsrep_thd_is_local_toi(const THD *thd) +{ + return thd->wsrep_cs().mode() == wsrep::client_state::m_toi && + thd->wsrep_cs().toi_mode() == wsrep::client_state::m_local; + +} + +extern "C" my_bool wsrep_thd_is_in_rsu(const THD *thd) +{ + return thd->wsrep_cs().mode() == wsrep::client_state::m_rsu; +} + +extern "C" my_bool wsrep_thd_is_BF(const THD *thd, my_bool sync) +{ + my_bool status = FALSE; + if (thd && WSREP(thd)) + { + if (sync) mysql_mutex_lock(&thd->LOCK_thd_data); + status = (wsrep_thd_is_applying(thd) || wsrep_thd_is_toi(thd)); + if (sync) mysql_mutex_unlock(&thd->LOCK_thd_data); + } + return status; +} + +extern "C" my_bool wsrep_thd_is_SR(const THD *thd) +{ + return thd && thd->wsrep_cs().transaction().is_streaming(); +} + +extern "C" void wsrep_handle_SR_rollback(THD *bf_thd, + THD *victim_thd) +{ + DBUG_ASSERT(victim_thd); + if (!victim_thd || !wsrep_on(bf_thd)) return; + + WSREP_DEBUG("handle rollback, for deadlock: thd %llu trx_id %lu frags %lu conf %s", + victim_thd->thread_id, + victim_thd->wsrep_trx_id(), + victim_thd->wsrep_sr().fragments_certified(), + wsrep_thd_transaction_state_str(victim_thd)); + if (bf_thd) victim_thd->store_globals(); + if (!bf_thd) + { + DEBUG_SYNC(victim_thd, "wsrep_before_SR_rollback"); + } + if (bf_thd) + { + wsrep_bf_abort(bf_thd, victim_thd); + } + else + { + wsrep_thd_self_abort(victim_thd); + } + if (bf_thd) bf_thd->store_globals(); +} + +extern "C" my_bool wsrep_thd_bf_abort(const THD *bf_thd, THD *victim_thd, + my_bool signal) +{ + if (WSREP(victim_thd) && !victim_thd->wsrep_trx().active()) + { + WSREP_DEBUG("BF abort for non active transaction"); + wsrep_start_transaction(victim_thd, victim_thd->wsrep_next_trx_id()); + } + my_bool ret= wsrep_bf_abort(bf_thd, victim_thd); + /* + Send awake signal if victim was BF aborted or does not + have wsrep on. Note that this should never interrupt RSU + as RSU has paused the provider. + */ + if ((ret || !wsrep_on(victim_thd)) && signal) + victim_thd->awake(KILL_QUERY); + return ret; +} + +extern "C" my_bool wsrep_thd_skip_locking(const THD *thd) +{ + return thd && thd->wsrep_skip_locking; +} + +extern "C" my_bool wsrep_thd_order_before(const THD *left, const THD *right) +{ + if (wsrep_thd_trx_seqno(left) < wsrep_thd_trx_seqno(right)) { + WSREP_DEBUG("BF conflict, order: %lld %lld\n", + (long long)wsrep_thd_trx_seqno(left), + (long long)wsrep_thd_trx_seqno(right)); + return TRUE; + } + WSREP_DEBUG("waiting for BF, trx order: %lld %lld\n", + (long long)wsrep_thd_trx_seqno(left), + (long long)wsrep_thd_trx_seqno(right)); + return FALSE; +} + +extern "C" my_bool wsrep_thd_is_aborting(const MYSQL_THD thd) +{ + mysql_mutex_assert_owner(&thd->LOCK_thd_data); + if (thd != 0) + { + const wsrep::client_state& cs(thd->wsrep_cs()); + const enum wsrep::transaction::state tx_state(cs.transaction().state()); + switch (tx_state) + { + case wsrep::transaction::s_must_abort: + return (cs.state() == wsrep::client_state::s_exec || + cs.state() == wsrep::client_state::s_result); + case wsrep::transaction::s_aborting: + case wsrep::transaction::s_aborted: + return true; + default: + return false; + } + } + return false; +} + +static inline enum wsrep::key::type +map_key_type(enum Wsrep_service_key_type type) +{ + switch (type) + { + case WSREP_SERVICE_KEY_SHARED: return wsrep::key::shared; + case WSREP_SERVICE_KEY_REFERENCE: return wsrep::key::reference; + case WSREP_SERVICE_KEY_UPDATE: return wsrep::key::update; + case WSREP_SERVICE_KEY_EXCLUSIVE: return wsrep::key::exclusive; + } + return wsrep::key::exclusive; +} + +extern "C" int wsrep_thd_append_key(THD *thd, + const struct wsrep_key* key, + int n_keys, + enum Wsrep_service_key_type key_type) +{ + Wsrep_client_state& client_state(thd->wsrep_cs()); + DBUG_ASSERT(client_state.transaction().active()); + int ret= 0; + for (int i= 0; i < n_keys && ret == 0; ++i) + { + wsrep::key wsrep_key(map_key_type(key_type)); + for (size_t kp= 0; kp < key[i].key_parts_num; ++kp) + { + wsrep_key.append_key_part(key[i].key_parts[kp].ptr, key[i].key_parts[kp].len); + } + ret= client_state.append_key(wsrep_key); + } + return ret; +} diff --git a/sql/slave.cc b/sql/slave.cc index 5fbe0c77661..f31021bc71e 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -53,6 +53,9 @@ // Create_file_log_event, // Format_description_log_event #include "wsrep_mysqld.h" +#ifdef WITH_WSREP +#include "wsrep_trans_observer.h" +#endif #ifdef HAVE_REPLICATION @@ -1201,6 +1204,11 @@ terminate_slave_thread(THD *thd, int error __attribute__((unused)); DBUG_PRINT("loop", ("killing slave thread")); +#ifdef WITH_WSREP + /* awake_no_mutex() requires LOCK_thd_data to be locked if wsrep + is enabled */ + if (WSREP(thd)) mysql_mutex_lock(&thd->LOCK_thd_data); +#endif /* WITH_WSREP */ mysql_mutex_lock(&thd->LOCK_thd_kill); #ifndef DONT_USE_THR_ALARM /* @@ -1214,6 +1222,9 @@ terminate_slave_thread(THD *thd, thd->awake_no_mutex(NOT_KILLED); mysql_mutex_unlock(&thd->LOCK_thd_kill); +#ifdef WITH_WSREP + if (WSREP(thd)) mysql_mutex_unlock(&thd->LOCK_thd_data); +#endif /* WITH_WSREP */ /* There is a small chance that slave thread might miss the first @@ -3943,14 +3954,20 @@ 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_thd_data); + if (exec_res && + thd->wsrep_trx().state() != wsrep::transaction::s_executing) { - WSREP_DEBUG("SQL apply failed, res %d conflict state: %d", - exec_res, thd->wsrep_conflict_state); + WSREP_DEBUG("SQL apply failed, res %d conflict state: %s", + exec_res, wsrep_thd_transaction_state_str(thd)); 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_thd_data); + } #endif #ifndef DBUG_OFF @@ -4243,6 +4260,13 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, } if (ev) { +#ifdef WITH_WSREP + if (wsrep_before_statement(thd)) + { + WSREP_INFO("Wsrep before statement error"); + DBUG_RETURN(1); + } +#endif /* WITH_WSREP */ int exec_res; Log_event_type typ= ev->get_type_code(); @@ -4274,9 +4298,9 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, rli->until_condition == Relay_log_info::UNTIL_RELAY_POS) && (ev->server_id != global_system_variables.server_id || rli->replicate_same_server_id) && - rli->is_until_satisfied((rli->get_flag(Relay_log_info::IN_TRANSACTION) || !ev->log_pos) - ? rli->group_master_log_pos - : ev->log_pos - ev->data_written)) + rli->is_until_satisfied((rli->get_flag(Relay_log_info::IN_TRANSACTION) || !ev->log_pos) + ? rli->group_master_log_pos + : ev->log_pos - ev->data_written)) { sql_print_information("Slave SQL thread stopped because it reached its" " UNTIL position %llu", rli->until_pos()); @@ -4287,6 +4311,9 @@ 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 + wsrep_after_statement(thd); +#endif /* WITH_WSREP */ delete ev; DBUG_RETURN(1); } @@ -4324,7 +4351,12 @@ 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 + wsrep_after_statement(thd); +#endif /* WITH_WSREP */ DBUG_RETURN(res); + } /* Else we proceed to execute the event non-parallel. This is the case for pre-10.0 events without GTID, and for handling @@ -4359,6 +4391,9 @@ 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 + wsrep_after_statement(thd); +#endif /* WITH_WSREP */ DBUG_RETURN(1); } @@ -4373,6 +4408,9 @@ 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 + wsrep_after_statement(thd); +#endif /* WITH_WSREP */ DBUG_RETURN(1); } /* @@ -4401,13 +4439,17 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, retry. */ if (unlikely(exec_res == 2)) + { +#ifdef WITH_WSREP + wsrep_after_statement(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_unlock(&thd->LOCK_thd_data); + enum wsrep::client_error wsrep_error= thd->wsrep_cs().current_error(); + mysql_mutex_unlock(&thd->LOCK_thd_data); + if (wsrep_error == wsrep::e_success) #endif /* WITH_WSREP */ if (slave_trans_retries) { @@ -4420,8 +4462,8 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, We were in a transaction which has been rolled back because of a temporary error; let's seek back to BEGIN log event and retry it all again. - Note, if lock wait timeout (innodb_lock_wait_timeout exceeded) - there is no rollback since 5.0.13 (ref: manual). + Note, if lock wait timeout (innodb_lock_wait_timeout exceeded) + there is no rollback since 5.0.13 (ref: manual). We have to not only seek but also a) init_master_info(), to seek back to hot relay log's start @@ -4482,13 +4524,11 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, serial_rgi->trans_retries)); } } -#ifdef WITH_WSREP - } - else - mysql_mutex_unlock(&thd->LOCK_thd_data); -#endif /* WITH_WSREP */ thread_safe_increment64(&rli->executed_entries); +#ifdef WITH_WSREP + wsrep_after_statement(thd); +#endif /* WITH_WSREP */ DBUG_RETURN(exec_res); } mysql_mutex_unlock(&rli->data_lock); @@ -5415,12 +5455,6 @@ pthread_handler_t handle_slave_sql(void *arg) } #endif -#ifdef WITH_WSREP - thd->wsrep_exec_mode= LOCAL_STATE; - /* synchronize with wsrep replication */ - if (WSREP_ON) - wsrep_ready_wait(); -#endif DBUG_PRINT("master_info",("log_file_name: %s position: %llu", rli->group_master_log_name, rli->group_master_log_pos)); @@ -5517,7 +5551,14 @@ pthread_handler_t handle_slave_sql(void *arg) goto err; } mysql_mutex_unlock(&rli->data_lock); - +#ifdef WITH_WSREP + wsrep_open(thd); + if (wsrep_before_command(thd)) + { + WSREP_WARN("Slave SQL wsrep_before_command() failed"); + goto err; + } +#endif /* WITH_WSREP */ /* Read queries from the IO/THREAD until this thread is killed */ thd->set_command(COM_SLAVE_SQL); @@ -5554,10 +5595,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_thd_data); + + if (thd->wsrep_cs().current_error()) + { + wsrep_node_dropped = TRUE; + rli->abort_slave = TRUE; + } + mysql_mutex_unlock(&thd->LOCK_thd_data); } #endif /* WITH_WSREP */ @@ -5590,6 +5637,10 @@ pthread_handler_t handle_slave_sql(void *arg) "log '%s' at position %llu%s", RPL_LOG_NAME, rli->group_master_log_pos, tmp.c_ptr_safe()); } +#ifdef WITH_WSREP + wsrep_after_command_before_result(thd); + wsrep_after_command_after_result(thd); +#endif /* WITH_WSREP */ err_before_start: @@ -5708,17 +5759,17 @@ err_during_init: "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 { + } + 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."); + "automatically restarted when node joins back to cluster"); wsrep_restart_slave_activated= TRUE; } } + wsrep_close(thd); #endif /* WITH_WSREP */ /* diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 56b4fc8c948..8345a9efe61 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -44,6 +44,9 @@ #include "transaction.h" // trans_commit_stmt #include "sql_audit.h" #include "debug_sync.h" +#ifdef WITH_WSREP +#include "wsrep_trans_observer.h" +#endif /* WITH_WSREP */ /* Sufficient max length of printed destinations and frame offsets (all uints). @@ -1324,6 +1327,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 +3576,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_trx().state() == wsrep::transaction::s_executing)) + { + /* + 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_statement(thd); + } +#endif /* WITH_WSREP */ MYSQL_QUERY_EXEC_DONE(res); *nextp= m_ip+1; return res; @@ -4503,8 +4531,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_acl.cc b/sql/sql_acl.cc index fe6fc9148bd..2edae501ccc 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3461,7 +3461,6 @@ wsrep_error_label: WSREP_TO_ISOLATION_END; thd->set_query(query_save); - thd->wsrep_exec_mode = LOCAL_STATE; } #endif /* WITH_WSREP */ thd->restore_stmt_binlog_format(save_binlog_format); @@ -3613,7 +3612,6 @@ wsrep_error_label: WSREP_TO_ISOLATION_END; thd->set_query(query_save); - thd->wsrep_exec_mode = LOCAL_STATE; } #endif /* WITH_WSREP */ diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc index 05a71d7785d..4e5ac6e9381 100644 --- a/sql/sql_alter.cc +++ b/sql/sql_alter.cc @@ -476,6 +476,7 @@ bool Sql_cmd_alter_table::execute(THD *thd) thd->work_part_info= 0; #endif +#ifdef WITH_WSREP if (WSREP(thd) && (!thd->is_current_stmt_binlog_format_row() || !thd->find_temporary_table(first_table))) @@ -487,6 +488,7 @@ bool Sql_cmd_alter_table::execute(THD *thd) thd->variables.auto_increment_offset = 1; thd->variables.auto_increment_increment = 1; } +#endif result= mysql_alter_table(thd, &select_lex->db, &lex->name, &create_info, diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 1b4ffd0c61e..ad7ff34190a 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -62,7 +62,11 @@ #include <io.h> #endif #include "wsrep_mysqld.h" +#ifdef WITH_WSREP #include "wsrep_thd.h" +#include "wsrep_trans_observer.h" +#endif /* WITH_WSREP */ + bool No_such_table_error_handler::handle_condition(THD *, @@ -4410,13 +4414,14 @@ restart: } } +#ifdef WITH_WSREP if (WSREP_ON && wsrep_replicate_myisam && (*start) && (*start)->table && (*start)->table->file->ht == myisam_hton && - wsrep_thd_exec_mode(thd) == LOCAL_STATE && - !is_stat_table(&(*start)->db, &(*start)->alias) && + wsrep_thd_is_local(thd) && + !is_stat_table(&(*start)->db, &(*start)->alias) && thd->get_command() != COM_STMT_PREPARE && ((thd->lex->sql_command == SQLCOM_INSERT || thd->lex->sql_command == SQLCOM_INSERT_SELECT || @@ -4427,8 +4432,12 @@ restart: thd->lex->sql_command == SQLCOM_LOAD || thd->lex->sql_command == SQLCOM_DELETE))) { - WSREP_TO_ISOLATION_BEGIN(NULL, NULL, (*start)); + wsrep_before_rollback(thd, true); + wsrep_after_rollback(thd, true); + wsrep_after_statement(thd); + WSREP_TO_ISOLATION_BEGIN(NULL, NULL, (*start)); } +#endif /* WITH_WSREP */ error: #ifdef WITH_WSREP diff --git a/sql/sql_class.cc b/sql/sql_class.cc index fa2f866a3f6..87e377c1819 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -66,8 +66,11 @@ #include "sql_callback.h" #include "lock.h" #include "wsrep_mysqld.h" -#include "wsrep_thd.h" #include "sql_connect.h" +#ifdef WITH_WSREP +#include "wsrep_thd.h" +#include "wsrep_trans_observer.h" +#endif /* WITH_WSREP */ #ifdef HAVE_SYS_SYSCALL_H #include <sys/syscall.h> @@ -639,16 +642,42 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock) xid_hash_pins(0), m_tmp_tables_locked(false) #ifdef WITH_WSREP - , + , wsrep_applier(is_wsrep_applier), wsrep_applier_closing(false), wsrep_client_thread(false), - wsrep_apply_toi(false), + wsrep_retry_counter(0), + wsrep_PA_safe(true), + wsrep_retry_query(NULL), + wsrep_retry_query_len(0), + wsrep_retry_command(COM_CONNECT), + wsrep_consistency_check(NO_CONSISTENCY_CHECK), + wsrep_mysql_replicated(0), + wsrep_TOI_pre_query(NULL), + wsrep_TOI_pre_query_len(0), wsrep_po_handle(WSREP_PO_INITIALIZER), wsrep_po_cnt(0), wsrep_apply_format(0), - wsrep_ignore_table(false) -#endif + wsrep_apply_toi(false), + wsrep_rbr_buf(NULL), + wsrep_sync_wait_gtid(WSREP_GTID_UNDEFINED), + wsrep_affected_rows(0), + wsrep_has_ignored_error(false), + wsrep_replicate_GTID(false), + wsrep_ignore_table(false), + +/* wsrep-lib */ + m_wsrep_next_trx_id(WSREP_UNDEFINED_TRX_ID), + m_wsrep_mutex(LOCK_thd_data), + m_wsrep_cond(COND_wsrep_thd), + m_wsrep_client_service(this, m_wsrep_client_state), + m_wsrep_client_state(this, + m_wsrep_mutex, + m_wsrep_cond, + Wsrep_server_state::instance(), + m_wsrep_client_service, + wsrep::client_id(thread_id)) +#endif /*WITH_WSREP */ { ulong tmp; bzero(&variables, sizeof(variables)); @@ -771,22 +800,8 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock) *scramble= '\0'; #ifdef WITH_WSREP - wsrep_ws_handle.trx_id = WSREP_UNDEFINED_TRX_ID; - wsrep_ws_handle.opaque = NULL; - wsrep_retry_counter = 0; - wsrep_PA_safe = true; - wsrep_retry_query = NULL; - wsrep_retry_query_len = 0; - wsrep_retry_command = COM_CONNECT; - wsrep_consistency_check = NO_CONSISTENCY_CHECK; - wsrep_mysql_replicated = 0; - wsrep_TOI_pre_query = NULL; - wsrep_TOI_pre_query_len = 0; + mysql_cond_init(key_COND_wsrep_thd, &COND_wsrep_thd, 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_replicate_GTID = false; - wsrep_skip_wsrep_GTID = false; #endif /* Call to init() below requires fully initialized Open_tables_state. */ reset_open_tables_state(this); @@ -1049,10 +1064,25 @@ Sql_condition* THD::raise_condition(uint sql_errno, is_slave_error= 1; // needed to catch query errors during replication - if (!da->is_error()) +#ifdef WITH_WSREP + /* + With wsrep we allow converting BF abort error to warning if + errors are ignored. + */ + if (!is_fatal_error && + no_errors && + (wsrep_trx().bf_aborted() || wsrep_retry_counter)) { - set_row_count_func(-1); - da->set_error_status(sql_errno, msg, sqlstate, ucid, cond); + WSREP_DEBUG("BF abort error converted to warning"); + } + else +#endif /* WITH_WSREP */ + { + if (!da->is_error()) + { + set_row_count_func(-1); + da->set_error_status(sql_errno, msg, sqlstate, ucid, cond); + } } } @@ -1113,6 +1143,13 @@ void *thd_memdup(MYSQL_THD thd, const void* str, size_t size) extern "C" void thd_get_xid(const MYSQL_THD thd, MYSQL_XID *xid) { +#ifdef WITH_WSREP + if (!thd->wsrep_xid.is_null()) + { + *xid = *(MYSQL_XID *) &thd->wsrep_xid; + } + else +#endif /* WITH_WSREP */ *xid = *(MYSQL_XID *) &thd->transaction.xid_state.xid; } @@ -1221,12 +1258,9 @@ void THD::init(bool skip_lock) first_successful_insert_id_in_cur_stmt= 0; current_backup_stage= BACKUP_FINISHED; #ifdef WITH_WSREP - wsrep_exec_mode= wsrep_applier ? REPL_RECV : LOCAL_STATE; - wsrep_conflict_state= NO_CONFLICT; - wsrep_query_state= QUERY_IDLE; wsrep_last_query_id= 0; - wsrep_trx_meta.gtid= WSREP_GTID_UNDEFINED; - wsrep_trx_meta.depends_on= WSREP_SEQNO_UNDEFINED; + wsrep_xid.null(); + wsrep_skip_locking= FALSE; wsrep_converted_lock_session= false; wsrep_retry_counter= 0; wsrep_rgi= NULL; @@ -1235,10 +1269,10 @@ void THD::init(bool skip_lock) wsrep_mysql_replicated = 0; wsrep_TOI_pre_query = NULL; wsrep_TOI_pre_query_len = 0; - wsrep_sync_wait_gtid = WSREP_GTID_UNDEFINED; + wsrep_rbr_buf = NULL; 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 */ if (variables.sql_log_bin) @@ -1467,6 +1501,13 @@ void THD::cleanup(void) #error xid_state in the cache should be replaced by the allocated value } #endif +#ifdef WITH_WSREP + if (wsrep_cs().state() != wsrep::client_state::s_none) + { + wsrep_cs().cleanup(); + } + wsrep_client_thread= false; +#endif /* WITH_WSREP */ mysql_ha_cleanup(this); locked_tables_list.unlock_locked_tables(this); @@ -1587,6 +1628,9 @@ void THD::reset_for_reuse() #ifdef SIGNAL_WITH_VIO_CLOSE active_vio = 0; #endif +#ifdef WITH_WSREP + wsrep_free_status(this); +#endif /* WITH_WSREP */ } @@ -1613,15 +1657,21 @@ 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_thd_data); mysql_mutex_lock(&LOCK_thd_kill); mysql_mutex_unlock(&LOCK_thd_kill); + if (WSREP(this)) mysql_mutex_unlock(&LOCK_thd_data); -#ifdef WITH_WSREP - delete wsrep_rgi; -#endif if (!free_connection_done) free_connection(); +#ifdef WITH_WSREP + if (wsrep_rgi != NULL) { + delete wsrep_rgi; + wsrep_rgi = NULL; + } + mysql_cond_destroy(&COND_wsrep_thd); +#endif mdl_context.destroy(); free_root(&transaction.mem_root,MYF(0)); @@ -1803,6 +1853,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_thd_data); mysql_mutex_assert_owner(&LOCK_thd_kill); print_aborted_warning(3, "KILLED"); @@ -1835,7 +1886,8 @@ void THD::awake_no_mutex(killed_state state_to_set) } /* Interrupt target waiting inside a storage engine. */ - if (state_to_set != NOT_KILLED) + if (IF_WSREP(state_to_set != NOT_KILLED && !wsrep_is_bf_aborted(this), + state_to_set != NOT_KILLED)) ha_kill_query(this, thd_kill_level(this)); /* Broadcast a condition to kick the target if it is waiting on it. */ @@ -1988,12 +2040,6 @@ bool THD::notify_shared_lock(MDL_context_owner *ctx_in_use, if (!thd_table->needs_reopen()) { signalled|= mysql_lock_abort_for_thread(this, thd_table); - if (WSREP(this) && wsrep_thd_is_BF(this, FALSE)) - { - WSREP_DEBUG("remove_table_from_cache: %llu", - (unsigned long long) this->real_id); - wsrep_abort_thd((void *)this, (void *)in_use, FALSE); - } } } } @@ -2225,12 +2271,6 @@ void THD::cleanup_after_query() /* reset table map for multi-table update */ table_map_for_update= 0; m_binlog_invoker= INVOKER_NONE; -#ifdef WITH_WSREP - if (TOTAL_ORDER == wsrep_exec_mode) - { - wsrep_exec_mode = LOCAL_STATE; - } -#endif /* WITH_WSREP */ #ifndef EMBEDDED_LIBRARY if (rgi_slave) @@ -2238,7 +2278,6 @@ void THD::cleanup_after_query() #endif #ifdef WITH_WSREP - wsrep_sync_wait_gtid= WSREP_GTID_UNDEFINED; if (!in_active_multi_stmt_transaction()) wsrep_affected_rows= 0; #endif /* WITH_WSREP */ @@ -5007,8 +5046,9 @@ extern "C" int thd_binlog_format(const MYSQL_THD thd) 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); } + if (mysql_bin_log.is_open() && (thd->variables.option_bits & OPTION_BIN_LOG)) return (int) thd->variables.binlog_format; return BINLOG_FORMAT_UNSPEC; @@ -5491,6 +5531,10 @@ 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 + set_wsrep_next_trx_id(query_id); + WSREP_DEBUG("assigned new next query and trx id: %lu", wsrep_next_trx_id()); +#endif /* WITH_WSREP */ } /** Assign a new value to thd->mysys_var. */ @@ -5936,9 +5980,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()) @@ -6260,7 +6322,8 @@ int THD::decide_logging_format(TABLE_LIST *tables) 5. Error: Cannot modify table that uses a storage engine limited to row-logging when binlog_format = STATEMENT */ - if (IF_WSREP((!WSREP(this) || wsrep_exec_mode == LOCAL_STATE),1)) + if (IF_WSREP((!WSREP(this) || + wsrep_cs().mode() == wsrep::client_state::m_local),1)) { my_error((error= ER_BINLOG_STMT_MODE_AND_ROW_ENGINE), MYF(0), ""); } diff --git a/sql/sql_class.h b/sql/sql_class.h index 69fabee708c..55eceda6c9f 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -60,8 +60,18 @@ void set_thd_stage_info(void *thd, #include "my_apc.h" #include "rpl_gtid.h" + #include "wsrep_mysqld.h" +#ifdef WITH_WSREP +/* wsrep-lib */ +#include "wsrep_client_service.h" +#include "wsrep_client_state.h" +#include "wsrep_mutex.h" +#include "wsrep_condition_variable.h" +class Wsrep_applier_service; + +#endif /* WITH_WSREP */ class Reprepare_observer; class Relay_log_info; struct rpl_group_info; @@ -712,10 +722,12 @@ typedef struct system_variables my_bool wsrep_on; my_bool wsrep_causal_reads; + uint wsrep_sync_wait; + ulong wsrep_retry_autocommit; + ulonglong 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; @@ -2235,7 +2247,7 @@ public: - thd->db (used in SHOW PROCESSLIST) Is locked when THD is deleted. */ - mysql_mutex_t LOCK_thd_data; + mutable mysql_mutex_t LOCK_thd_data; /* Protects: - kill information @@ -3196,7 +3208,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. @@ -3204,7 +3215,6 @@ public: query_id_t first_query_id; } binlog_evt_union; - mysql_cond_t COND_wsrep_thd; /** Internal parser state. Note that since the parser is not re-entrant, we keep only one parser @@ -3287,9 +3297,18 @@ public: void awake_no_mutex(killed_state state_to_set); void awake(killed_state state_to_set) { + bool wsrep_on_local= WSREP_ON; + /* + mutex locking order (LOCK_thd_data - LOCK_thd_kill)) requires + to grab LOCK_thd_data here + */ + if (wsrep_on_local) + mysql_mutex_lock(&LOCK_thd_data); mysql_mutex_lock(&LOCK_thd_kill); awake_no_mutex(state_to_set); mysql_mutex_unlock(&LOCK_thd_kill); + if (wsrep_on_local) + mysql_mutex_unlock(&LOCK_thd_data); } /** Disconnect the associated communication endpoint. */ @@ -4497,6 +4516,13 @@ public: void set_query_id(query_id_t new_query_id) { query_id= new_query_id; +#ifdef WITH_WSREP + if (WSREP(this)) + { + 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) { @@ -4752,52 +4778,114 @@ private: public: inline ulong wsrep_binlog_format() const { - return WSREP_FORMAT(variables.binlog_format); + return WSREP_BINLOG_FORMAT(variables.binlog_format); } #ifdef WITH_WSREP - const bool wsrep_applier; /* dedicated slave applier thread */ + 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; - wsrep_trx_meta_t wsrep_trx_meta; + 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; + + mysql_cond_t COND_wsrep_thd; + + // changed from wsrep_seqno_t to wsrep_trx_meta_t in wsrep API rev 75 uint32 wsrep_rand; - Relay_log_info *wsrep_rli; rpl_group_info *wsrep_rgi; - wsrep_ws_handle_t wsrep_ws_handle; + bool wsrep_converted_lock_session; + char wsrep_info[128]; /* string for dynamic 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; + std::vector<wsrep::provider::status_variable> 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 */ + bool wsrep_apply_toi; /* applier processing in TOI */ + uchar* wsrep_rbr_buf; + 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; + /* When enabled, do not replicate/binlog updates from the current table that's being processed. At the moment, it is used to keep mysql.gtid_slave_pos table updates from being replicated to other nodes via galera replication. */ bool wsrep_ignore_table; - wsrep_gtid_t wsrep_sync_wait_gtid; - ulong wsrep_affected_rows; - bool wsrep_replicate_GTID; - bool wsrep_skip_wsrep_GTID; + + + /* + 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() + 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 m_wsrep_client_state.transaction().id().get(); + } + + + /* + Set next trx id + */ + void set_wsrep_next_trx_id(query_id_t query_id) + { + 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 */ + /* wsrep-lib */ + Wsrep_mutex m_wsrep_mutex; + Wsrep_condition_variable m_wsrep_cond; + Wsrep_client_service m_wsrep_client_service; + Wsrep_client_state m_wsrep_client_state; + +public: + Wsrep_client_state& wsrep_cs() { return m_wsrep_client_state; } + const Wsrep_client_state& wsrep_cs() const { return m_wsrep_client_state; } + const wsrep::transaction& wsrep_trx() const + { return m_wsrep_client_state.transaction(); } + const wsrep::streaming_context& wsrep_sr() const + { return m_wsrep_client_state.transaction().streaming_context(); } + /* Pointer to applier service for streaming THDs. This is needed to + be able to delete applier service object in case of background + rollback. */ + Wsrep_applier_service* wsrep_applier_service; #endif /* WITH_WSREP */ /* Handling of timeouts for commands */ @@ -6304,7 +6392,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. @@ -6322,7 +6410,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. @@ -6398,6 +6486,14 @@ public: */ #define CF_DB_CHANGE (1U << 22) +#ifdef WITH_WSREP +/** + DDL statement that may be subject to error filtering. +*/ +#define CF_WSREP_MAY_IGNORE_ERRORS (1U << 23) +#endif /* WITH_WSREP */ + + /* Bits in server_command_flags */ /** diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index b48070b9c8f..ec46d84c7ce 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -37,7 +37,11 @@ // reset_host_errors #include "sql_acl.h" // acl_getroot, NO_ACCESS, SUPER_ACL #include "sql_callback.h" + +#ifdef WITH_WSREP +#include "wsrep_trans_observer.h" /* wsrep open/close */ #include "wsrep_mysqld.h" +#endif /* WITH_WSREP */ #include "proxy_protocol.h" HASH global_user_stats, global_client_stats, global_table_stats; @@ -1177,17 +1181,6 @@ exit: void end_connection(THD *thd) { NET *net= &thd->net; -#ifdef WITH_WSREP - if (WSREP(thd)) - { - wsrep_status_t rcode= wsrep->free_connection(wsrep, thd->thread_id); - if (rcode) { - WSREP_WARN("wsrep failed to free connection context: %lld code: %d", - (longlong) thd->thread_id, rcode); - } - } - thd->wsrep_client_thread= 0; -#endif plugin_thdvar_cleanup(thd); if (thd->user_connect) @@ -1322,7 +1315,7 @@ bool thd_prepare_connection(THD *thd) prepare_new_connection_state(thd); #ifdef WITH_WSREP - thd->wsrep_client_thread= 1; + thd->wsrep_client_thread= true; #endif /* WITH_WSREP */ return FALSE; } @@ -1395,6 +1388,9 @@ void do_handle_one_connection(CONNECT *connect) create_user= FALSE; goto end_thread; } +#ifdef WITH_WSREP + wsrep_open(thd); +#endif /* WITH_WSREP */ while (thd_is_connection_alive(thd)) { @@ -1405,13 +1401,9 @@ void do_handle_one_connection(CONNECT *connect) end_connection(thd); #ifdef WITH_WSREP - if (WSREP(thd)) - { - mysql_mutex_lock(&thd->LOCK_thd_data); - thd->wsrep_query_state= QUERY_EXITING; - mysql_mutex_unlock(&thd->LOCK_thd_data); - } -#endif + wsrep_close(thd); +#endif /* WITH_WSREP */ + end_thread: close_connection(thd); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index f5e4185db92..785d7c12bd2 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -82,6 +82,10 @@ #include "debug_sync.h" +#ifdef WITH_WSREP +#include "wsrep_trans_observer.h" /* wsrep_start_transction() */ +#endif /* WITH_WSREP */ + #ifndef EMBEDDED_LIBRARY static bool delayed_get_table(THD *thd, MDL_request *grl_protection_request, TABLE_LIST *table_list); @@ -3934,10 +3938,13 @@ 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)); +#ifdef WITH_WSREP + error= (thd->wsrep_cs().current_error()) ? -1 : + (thd->locked_tables_mode <= LTM_LOCK_TABLES) ? +#else + error= (thd->locked_tables_mode <= LTM_LOCK_TABLES) ? +#endif /* WITH_WSREP */ + table->file->ha_end_bulk_insert() : 0; if (likely(!error) && unlikely(thd->is_error())) error= thd->get_stmt_da()->sql_errno(); @@ -4534,9 +4541,16 @@ select_create::binlog_show_create_table(TABLE **tables, uint count) /* suppress_use */ FALSE, errcode); } - - ha_fake_trx_id(thd); - +#ifdef WITH_WSREP + if (thd->wsrep_trx().active()) + { + WSREP_DEBUG("transaction already started for CTAS"); + } + else + { + wsrep_start_transaction(thd, thd->wsrep_next_trx_id()); + } +#endif return result; } @@ -4594,10 +4608,18 @@ bool select_create::send_eof() if (!table->s->tmp_table) { #ifdef WITH_WSREP - if (WSREP_ON) + if (WSREP(thd)) { + if (thd->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID) + { + wsrep_start_transaction(thd, 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, @@ -4605,38 +4627,34 @@ 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_thd_append_key(thd, key_arr.keys, key_arr.keys_len, + WSREP_SERVICE_KEY_EXCLUSIVE); 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)) ? wsrep_thd_query(thd) : "void", rcode); - return true; + DBUG_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); if (!(thd->variables.option_bits & OPTION_GTID_BEGIN)) trans_commit_implicit(thd); #ifdef WITH_WSREP - if (WSREP_ON) + if (WSREP(thd)) { thd->get_stmt_da()->set_overwrite_status(FALSE); mysql_mutex_lock(&thd->LOCK_thd_data); - if (thd->wsrep_conflict_state != NO_CONFLICT) + if (wsrep_current_error(thd)) { - 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: %llu err: %s %s", + thd->thread_id, + wsrep_thd_transaction_state_str(thd), WSREP_QUERY(thd)); mysql_mutex_unlock(&thd->LOCK_thd_data); abort_result_set(); DBUG_RETURN(true); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 416180f0006..24de741cefd 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1860,7 +1860,7 @@ int Lex_input_stream::lex_one_token(YYSTYPE *yylval, THD *thd) else { #ifdef WITH_WSREP - if (WSREP(thd) && version == 99997 && thd->wsrep_exec_mode == LOCAL_STATE) + if (WSREP(thd) && version == 99997 && wsrep_thd_is_local(thd)) { WSREP_DEBUG("consistency check: %s", thd->query()); thd->wsrep_consistency_check= CONSISTENCY_CHECK_DECLARED; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index dd6e723c953..c95ef72a308 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 @@ -116,13 +118,10 @@ static bool wsrep_load_data_split(THD *thd, const TABLE *table, if (handlerton* hton= thd->transaction.stmt.ha_list->next()->ht()) { - if (hton->db_type != DB_TYPE_INNODB) + if (!(hton->flags & HTON_WSREP_REPLICATION)) DBUG_RETURN(false); WSREP_DEBUG("intermediate transaction commit in LOAD DATA"); - 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); + wsrep_tc_log_commit(thd); table->file->extra(HA_EXTRA_FAKE_START_STMT); } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 65b52b5b5da..34c690416ad 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -111,13 +111,16 @@ #include "wsrep.h" #include "wsrep_mysqld.h" +#ifdef WITH_WSREP #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); +#endif /* WITH_WSREP */ /** @defgroup Runtime_Environment Runtime Environment @{ @@ -884,6 +887,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) @@ -1208,28 +1221,11 @@ bool do_command(THD *thd) { bool return_value; char *packet= 0; -#ifdef WITH_WSREP - ulong packet_length= 0; // just to avoid (false positive) compiler warning -#else ulong packet_length; -#endif /* WITH_WSREP */ NET *net= &thd->net; 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) @@ -1270,29 +1266,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)) { @@ -1300,20 +1273,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]. @@ -1364,13 +1323,52 @@ bool do_command(THD *thd) command= fetch_command(thd, packet); #ifdef WITH_WSREP + /* + Aborted by background rollbacker thread. + Handle error here and jump straight to out + */ + if (wsrep_before_command(thd)) + { + thd->store_globals(); + WSREP_LOG_THD(thd, "enter found BF aborted"); + DBUG_ASSERT(!thd->mdl_context.has_locks()); + DBUG_ASSERT(!thd->get_stmt_da()->is_set()); + /* We let COM_QUIT and COM_STMT_CLOSE to execute even if wsrep aborted. */ + if (command != COM_STMT_CLOSE && + command != COM_QUIT) + { + my_error(ER_LOCK_DEADLOCK, MYF(0)); + WSREP_DEBUG("Deadlock error for: %s", thd->query()); + thd->reset_killed(); + thd->mysys_var->abort = 0; + thd->wsrep_retry_counter = 0; + + /* Instrument this broken statement as "statement/com/error" */ + thd->m_statement_psi= MYSQL_REFINE_STATEMENT(thd->m_statement_psi, + com_statement_info[COM_END]. + m_key); + + thd->protocol->end_statement(); + + /* Mark the statement completed. */ + MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da()); + thd->m_statement_psi= NULL; + thd->m_digest= NULL; + return_value= FALSE; + + wsrep_after_command_before_result(thd); + goto out; + } + } + if (WSREP(thd)) { /* - Bail out if DB snapshot has not been installed. - */ - if (!thd->wsrep_applier && - (!wsrep_ready || wsrep_reject_queries != WSREP_REJECT_NONE) && + * bail out if DB snapshot has not been installed. We however, + * allow queries "SET" and "SHOW", they are trapped later in execute_command + */ + if (!(thd->wsrep_applier) && + (!wsrep_ready_get() || wsrep_reject_queries != WSREP_REJECT_NONE) && (server_command_flags[command] & CF_SKIP_WSREP_CHECK) == 0) { my_message(ER_UNKNOWN_COM_ERROR, @@ -1383,11 +1381,11 @@ bool do_command(THD *thd) thd->m_digest= NULL; return_value= FALSE; + wsrep_after_command_before_result(thd); goto out; } } -#endif - +#endif /* WITH_WSREP */ /* Restore read timeout value */ my_net_set_read_timeout(net, thd->variables.net_read_timeout); @@ -1395,37 +1393,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: @@ -1433,6 +1400,13 @@ out: /* The statement instrumentation must be closed in all cases. */ DBUG_ASSERT(thd->m_digest == NULL); DBUG_ASSERT(thd->m_statement_psi == NULL); +#ifdef WITH_WSREP + if (packet_length != packet_error) + { + /* there was a command to process, and before_command() has been called */ + wsrep_after_command_after_result(thd); + } +#endif /* WITH_WSREP */ DBUG_RETURN(return_value); } #endif /* EMBEDDED_LIBRARY */ @@ -1498,6 +1472,36 @@ static bool deny_updates_if_read_only_option(THD *thd, TABLE_LIST *all_tables) DBUG_RETURN(FALSE); } +#ifdef WITH_WSREP +static my_bool wsrep_read_only_option(THD *thd, TABLE_LIST *all_tables) +{ + int opt_readonly_saved = opt_readonly; + ulong flag_saved = (ulong)(thd->security_ctx->master_access & SUPER_ACL); + + opt_readonly = 0; + thd->security_ctx->master_access &= ~SUPER_ACL; + + my_bool ret = !deny_updates_if_read_only_option(thd, all_tables); + + opt_readonly = opt_readonly_saved; + thd->security_ctx->master_access |= flag_saved; + + return ret; +} + +static void wsrep_copy_query(THD *thd) +{ + thd->wsrep_retry_command = thd->get_command(); + thd->wsrep_retry_query_len = thd->query_length(); + if (thd->wsrep_retry_query) { + my_free(thd->wsrep_retry_query); + } + thd->wsrep_retry_query = (char *)my_malloc( + thd->wsrep_retry_query_len + 1, MYF(0)); + strncpy(thd->wsrep_retry_query, thd->query(), thd->wsrep_retry_query_len); + thd->wsrep_retry_query[thd->wsrep_retry_query_len] = '\0'; +} +#endif /* WITH_WSREP */ /** check COM_MULTI packet @@ -1580,41 +1584,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* keep it withing 1 byte */ compile_time_assert(COM_END == 255); -#ifdef WITH_WSREP - if (WSREP(thd)) - { - if (!thd->in_multi_stmt_transaction_mode()) - { - thd->wsrep_PA_safe= true; - } - - 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) - { - mysql_mutex_unlock(&thd->LOCK_thd_data); - my_message(ER_LOCK_DEADLOCK, "Deadlock: wsrep aborted transaction", - MYF(0)); - WSREP_DEBUG("Deadlock error for: %s", thd->query()); - thd->reset_killed(); - thd->mysys_var->abort = 0; - thd->wsrep_conflict_state = NO_CONFLICT; - thd->wsrep_retry_counter = 0; - goto dispatch_end; - } - mysql_mutex_unlock(&thd->LOCK_thd_data); - } -#endif /* WITH_WSREP */ #if defined(ENABLED_PROFILING) thd->profiling.start_new_query(); #endif @@ -1661,6 +1630,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); @@ -1844,10 +1820,24 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (unlikely(parser_state.init(thd, thd->query(), thd->query_length()))) break; +#ifdef WITH_WSREP 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_thd_data); + thd->killed = NOT_KILLED; + thd->mysys_var->abort = 0; + thd->wsrep_retry_counter = 0; + mysql_mutex_unlock(&thd->LOCK_thd_data); + goto dispatch_end; + } + } else +#endif /* WITH_WSREP */ mysql_parse(thd, thd->query(), thd->query_length(), &parser_state, is_com_multi, is_next_command); @@ -1929,17 +1919,32 @@ bool dispatch_command(enum enum_server_command command, THD *thd, */ statistic_increment(thd->status_var.questions, &LOCK_status); - if(!WSREP(thd)) - thd->set_time(); /* Reset the query start time. */ + if (!WSREP(thd)) + thd->set_time(); /* Reset the query start time. */ parser_state.reset(beginning_of_next_stmt, length); +#ifdef WITH_WSREP 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_thd_data); + thd->killed = NOT_KILLED; + thd->mysys_var->abort = 0; + thd->wsrep_retry_counter = 0; + mysql_mutex_unlock(&thd->LOCK_thd_data); + + goto dispatch_end; + } + } else - mysql_parse(thd, beginning_of_next_stmt, length, &parser_state, - is_com_multi, is_next_command); +#endif /* WITH_WSREP */ + mysql_parse(thd, beginning_of_next_stmt, length, &parser_state, + is_com_multi, is_next_command); } @@ -2376,7 +2381,26 @@ com_multi_end: #ifdef WITH_WSREP dispatch_end: - + /* + BF aborted before sending response back to client + */ + if (thd->killed == KILL_QUERY) + { + WSREP_DEBUG("THD is killed at dispatch_end"); + } + wsrep_after_command_before_result(thd); + if (wsrep_current_error(thd) && + !(command == COM_STMT_PREPARE || + command == COM_STMT_FETCH || + command == COM_STMT_SEND_LONG_DATA || + command == COM_STMT_CLOSE + )) + { + /* todo: Pass wsrep client state current error to override */ + wsrep_override_error(thd, wsrep_current_error(thd), + wsrep_current_error_status(thd)); + WSREP_LOG_THD(thd, "leave"); + } if (WSREP(thd)) { /* @@ -2387,9 +2411,10 @@ com_multi_end: || 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 && - !thd->killed; + do_end_of_statement= + thd->wsrep_trx().state() != wsrep::transaction::s_replaying + && !thd->killed; + mysql_mutex_unlock(&thd->LOCK_thd_data); } else @@ -3423,7 +3448,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 @@ -3453,8 +3478,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) && + !(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) && @@ -3619,7 +3644,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 @@ -3642,6 +3667,13 @@ mysql_execute_command(THD *thd) } } thd->transaction.stmt.mark_trans_did_ddl(); +#ifdef WITH_WSREP + /* Clean up the previous transaction on implicit commit */ + if (wsrep_thd_is_local(thd) && wsrep_after_statement(thd)) + { + goto error; + } +#endif /* WITH_WSREP */ } #ifndef DBUG_OFF @@ -3690,6 +3722,33 @@ mysql_execute_command(THD *thd) /* Start timeouts */ thd->set_query_timer(); +#ifdef WITH_WSREP + /* + Always start a new transaction for a wsrep THD unless the + current command is DDL or explicit BEGIN. This will guarantee that + the THD is BF abortable even if it does not generate any + changes and takes only read locks. If the statement does not + start a multi STMT transaction, the wsrep_transaction is + committed as empty at the end of this function. + + Transaction is started for BEGIN in trans_begin(), for DDL the + implicit commit took care of committing previous transaction + above and a new transaction should not be started. + + Do not start transaction for stored procedures, it will be handled + internally in SP processing. + */ + if (WSREP(thd) && + wsrep_thd_is_local(thd) && + lex->sql_command != SQLCOM_BEGIN && + lex->sql_command != SQLCOM_CALL && + lex->sql_command != SQLCOM_EXECUTE && + !(sql_command_flags[lex->sql_command] & CF_AUTO_COMMIT_TRANS)) + { + wsrep_start_trx_if_not_started(thd); + } +#endif /* WITH_WSREP */ + switch (lex->sql_command) { case SQLCOM_SHOW_EVENTS: @@ -3749,12 +3808,16 @@ mysql_execute_command(THD *thd) case SQLCOM_SHOW_STORAGE_ENGINES: case SQLCOM_SHOW_PROFILE: 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) + 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; @@ -4555,9 +4618,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; @@ -4706,9 +4767,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 @@ -4766,9 +4825,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; @@ -4888,9 +4945,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; @@ -4950,9 +5005,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; @@ -5793,6 +5846,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); @@ -5832,20 +5886,7 @@ end_with_restore_list: thd->set_killed(KILL_CONNECTION); thd->print_aborted_warning(3, "RELEASE"); } -#ifdef WITH_WSREP - if (WSREP(thd)) { - - if (thd->wsrep_conflict_state == NO_CONFLICT || - thd->wsrep_conflict_state == REPLAYING) - { - my_ok(thd); - } - } else { -#endif /* WITH_WSREP */ - my_ok(thd); -#ifdef WITH_WSREP - } -#endif /* WITH_WSREP */ + my_ok(thd); break; } case SQLCOM_ROLLBACK: @@ -5881,17 +5922,7 @@ end_with_restore_list: /* Disconnect the current client connection. */ if (tx_release) thd->set_killed(KILL_CONNECTION); -#ifdef WITH_WSREP - if (WSREP(thd)) { - if (thd->wsrep_conflict_state == NO_CONFLICT) { - my_ok(thd); - } - } else { -#endif /* WITH_WSREP */ - my_ok(thd); -#ifdef WITH_WSREP - } -#endif /* WITH_WSREP */ + my_ok(thd); break; } case SQLCOM_RELEASE_SAVEPOINT: @@ -6338,7 +6369,6 @@ finish: DBUG_ASSERT(!thd->in_active_multi_stmt_transaction() || thd->in_multi_stmt_transaction_mode()); - lex->unit.cleanup(); /* close/reopen tables that were marked to need reopen under LOCK TABLES */ @@ -6364,25 +6394,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. */ @@ -6398,9 +6409,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 @@ -6462,9 +6470,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. */ @@ -6477,11 +6486,26 @@ finish: (longlong) thd->thread_id); thd->mdl_context.release_transactional_locks(); } + + /* + Current command did not start multi STMT transaction and the command + did not cause commit to happen (e.g. read only). Commit the wsrep + transaction as empty. + */ + if (!thd->in_active_multi_stmt_transaction() && + !thd->in_sub_stmt && + thd->wsrep_trx().active() && + thd->wsrep_trx().state() == wsrep::transaction::s_executing) + { + wsrep_commit_empty(thd, true); + } + + /* 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) { @@ -6607,6 +6631,7 @@ 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); @@ -6625,6 +6650,10 @@ 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; +#ifdef WITH_WSREP +wsrep_error_label: /* see WSREP_SYNC_WAIT() macro above */ + return true; +#endif /* WITH_WSREP */ } @@ -7654,7 +7683,7 @@ void THD::reset_for_next_command(bool do_clear_error) use autoinc values passed in binlog events, not the values forced by the cluster. */ - if (WSREP(this) && wsrep_exec_mode == LOCAL_STATE && + if (WSREP(this) && wsrep_thd_is_local(this) && !slave_thread && wsrep_auto_increment_control) { variables.auto_increment_offset= @@ -7872,144 +7901,155 @@ 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, +#ifdef WITH_WSREP +static void wsrep_prepare_for_autocommit_retry(THD* thd, + char* rawbuf, + uint length, + Parser_state* parser_state) +{ + thd->clear_error(); + close_thread_tables(thd); + thd->wsrep_retry_counter++; // grow + wsrep_copy_query(thd); + thd->set_time(); + parser_state->reset(rawbuf, length); + + /* 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()) + { + 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, + thd->get_db(), + &thd->security_ctx->priv_user[0], + (char *) thd->security_ctx->host_or_ip); + + /* Performance Schema Interface instrumentation, begin */ + thd->m_statement_psi= MYSQL_REFINE_STATEMENT(thd->m_statement_psi, + com_statement_info[thd->get_command()].m_key); + MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi, thd->query(), + thd->query_length()); + + DBUG_ASSERT(thd->wsrep_trx().active() == false); + thd->wsrep_cs().reset_error(); + thd->set_query_id(next_query_id()); +} + +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 bool is_autocommit= !thd->in_multi_stmt_transaction_mode() && - thd->wsrep_conflict_state == NO_CONFLICT && - !thd->wsrep_applier; - + wsrep_read_only_option(thd, thd->lex->query_tables); + bool retry_autocommit; do { - if (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT) - { - thd->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); - MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi, thd->query(), - thd->query_length()); - - DBUG_EXECUTE_IF("sync.wsrep_retry_autocommit", - { - const char act[]= - "now " - "SIGNAL wsrep_retry_autocommit_reached " - "WAIT_FOR wsrep_retry_autocommit_continue"; - DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); - }); - WSREP_DEBUG("Retry autocommit query: %s", thd->query()); - } - - mysql_parse(thd, rawbuf, length, parser_state, is_com_multi, - is_next_command); - - if (WSREP(thd)) { - /* wsrep BF abort in query exec phase */ - mysql_mutex_lock(&thd->LOCK_thd_data); - if (thd->wsrep_conflict_state == MUST_ABORT) { - wsrep_client_rollback(thd); - - WSREP_DEBUG("abort in exec query state, avoiding autocommit"); - } + retry_autocommit= false; + mysql_parse(thd, rawbuf, length, parser_state, is_com_multi, is_next_command); - if (thd->wsrep_conflict_state == MUST_REPLAY) - { - mysql_mutex_unlock(&thd->LOCK_thd_data); - if (thd->lex->explain) - delete_explain_query(thd->lex); - mysql_mutex_lock(&thd->LOCK_thd_data); + /* + Convert all ER_QUERY_INTERRUPTED errors to ER_LOCK_DEADLOCK + if the transaction was BF aborted. This can happen when the + transaction is being BF aborted via thd->awake() while it is + still executing. - wsrep_replay_transaction(thd); - } + Note that this must be done before wsrep_after_statement() call + since it clears the transaction for autocommit queries. + */ + if (((thd->get_stmt_da()->is_error() && + thd->get_stmt_da()->sql_errno() == ER_QUERY_INTERRUPTED) || + !thd->get_stmt_da()->is_set()) && + thd->wsrep_trx().bf_aborted()) + { + WSREP_DEBUG("overriding error: %d with DEADLOCK", + (thd->get_stmt_da()->is_error()) ? + thd->get_stmt_da()->sql_errno() : 0); - /* setting error code for BF aborted trxs */ - if (thd->wsrep_conflict_state == ABORTED || - thd->wsrep_conflict_state == CERT_FAILURE) - { - thd->reset_for_next_command(); - if (is_autocommit && - thd->lex->sql_command != SQLCOM_SELECT && - (thd->wsrep_retry_counter < thd->variables.wsrep_retry_autocommit)) - { - mysql_mutex_unlock(&thd->LOCK_thd_data); - WSREP_DEBUG("wsrep retrying AC query: %s", - (thd->query()) ? thd->query() : "void"); - - /* Performance Schema Interface instrumentation, end */ - MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da()); - thd->m_statement_psi= NULL; - thd->m_digest= NULL; - // Released thd->LOCK_thd_data above as below could end up - // close_thread_tables()/close_open_tables()/close_thread_table()/mysql_mutex_lock(&thd->LOCK_thd_data) - close_thread_tables(thd); - - mysql_mutex_lock(&thd->LOCK_thd_data); - thd->wsrep_conflict_state= RETRY_AUTOCOMMIT; - thd->wsrep_retry_counter++; // grow - wsrep_copy_query(thd); - thd->set_time(); - parser_state->reset(rawbuf, length); - mysql_mutex_unlock(&thd->LOCK_thd_data); - } - else - { - mysql_mutex_unlock(&thd->LOCK_thd_data); - // This does dirty read to wsrep variables but it is only a debug code - WSREP_DEBUG("%s, thd: %lld is_AC: %d, retry: %lu - %lu SQL: %s", - (thd->wsrep_conflict_state == 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)); - - mysql_mutex_lock(&thd->LOCK_thd_data); - thd->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->killed = NOT_KILLED; + wsrep_override_error(thd, ER_LOCK_DEADLOCK); + } - thd->reset_killed(); + if (wsrep_after_statement(thd) && is_autocommit) + { + thd->reset_for_next_command(); + thd->killed= NOT_KILLED; + if (is_autocommit && + thd->lex->sql_command != SQLCOM_SELECT && + thd->wsrep_retry_counter < thd->variables.wsrep_retry_autocommit) + { + DBUG_EXECUTE_IF("sync.wsrep_retry_autocommit", + { + const char act[]= + "now " + "SIGNAL wsrep_retry_autocommit_reached " + "WAIT_FOR wsrep_retry_autocommit_continue"; + DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); + }); + WSREP_DEBUG("wsrep retrying AC query: %lu %s", + thd->wsrep_retry_counter, WSREP_QUERY(thd)); + wsrep_prepare_for_autocommit_retry(thd, rawbuf, length, parser_state); + if (thd->lex->explain) + delete_explain_query(thd->lex); + retry_autocommit= true; } else { - set_if_smaller(thd->wsrep_retry_counter, 0); // reset; eventually ok - mysql_mutex_unlock(&thd->LOCK_thd_data); + WSREP_DEBUG("%s, thd: %llu is_AC: %d, retry: %lu - %lu SQL: %s", + wsrep_thd_transaction_state_str(thd), + thd->thread_id, + is_autocommit, + thd->wsrep_retry_counter, + thd->variables.wsrep_retry_autocommit, + WSREP_QUERY(thd)); + my_error(ER_LOCK_DEADLOCK, MYF(0)); + thd->killed= NOT_KILLED; + thd->wsrep_retry_counter= 0; // reset } } - - /* If retry is requested clean up explain structure */ - if ((thd->wsrep_conflict_state == RETRY_AUTOCOMMIT || - thd->wsrep_conflict_state == MUST_REPLAY ) - && thd->lex->explain) + else { - delete_explain_query(thd->lex); + set_if_smaller(thd->wsrep_retry_counter, 0); // reset; eventually ok } - - } while (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT); + } while (retry_autocommit); 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(), + WSREP_DEBUG("releasing retry_query: " + "conf %s sent %d kill %d errno %d SQL %s", + wsrep_thd_transaction_state_str(thd), + 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; thd->wsrep_retry_query_len = 0; thd->wsrep_retry_command = COM_CONNECT; } -#endif /* WITH_WSREP */ + return false; } +#endif /* WITH_WSREP */ /* @@ -8961,6 +9001,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_thd_data); mysql_mutex_lock(&tmp->LOCK_thd_kill); // Lock from delete break; } @@ -8989,7 +9030,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 %llu", thd->thread_id); if (id && (tmp= find_thread_by_id(id, type == KILL_TYPE_QUERY))) { /* @@ -9013,9 +9054,14 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ faster and do a harder kill than KILL_SYSTEM_THREAD; */ +#ifdef WITH_WSREP 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(tmp, false) && !tmp->wsrep_applier) +#else + if ((thd->security_ctx->master_access & SUPER_ACL) || + thd->security_ctx->user_matches(tmp->security_ctx)) +#endif /* WITH_WSREP */ { tmp->awake_no_mutex(kill_signal); error=0; @@ -9024,6 +9070,7 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ 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_thd_data); } DBUG_PRINT("exit", ("%d", error)); DBUG_RETURN(error); @@ -9081,7 +9128,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_thd_data); mysql_mutex_lock(&tmp->LOCK_thd_kill); // Lock from delete + } } } mysql_mutex_unlock(&LOCK_thread_count); @@ -9103,6 +9153,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_thd_data); (*rows)++; } while ((ptr= next_ptr)); } diff --git a/sql/sql_plugin_services.ic b/sql/sql_plugin_services.ic index c730490a499..8893ea361e3 100644 --- a/sql/sql_plugin_services.ic +++ b/sql/sql_plugin_services.ic @@ -142,47 +142,35 @@ static struct thd_error_context_service_st thd_error_context_handler= { }; static struct wsrep_service_st wsrep_handler = { - get_wsrep, - get_wsrep_certify_nonPK, - get_wsrep_debug, - get_wsrep_drupal_282555_workaround, get_wsrep_recovery, - 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_conflict_state_str, - wsrep_thd_exec_mode, - wsrep_thd_exec_mode_str, - wsrep_thd_get_conflict_state, - wsrep_thd_is_BF, - wsrep_thd_is_wsrep, wsrep_thd_query, - wsrep_thd_query_state, - wsrep_thd_query_state_str, wsrep_thd_retry_counter, - wsrep_thd_set_conflict_state, wsrep_thd_ignore_table, wsrep_thd_trx_seqno, - wsrep_thd_ws_handle, - wsrep_trx_is_aborting, - wsrep_trx_order_before, - wsrep_unlock_rollback, - wsrep_set_data_home_dir + wsrep_thd_is_aborting, + wsrep_set_data_home_dir, + wsrep_thd_is_BF, + wsrep_thd_is_local, + wsrep_thd_self_abort, + wsrep_thd_append_key, + wsrep_thd_client_state_str, + wsrep_thd_client_mode_str, + wsrep_thd_transaction_state_str, + wsrep_thd_transaction_id, + wsrep_thd_bf_abort, + wsrep_thd_order_before, + wsrep_handle_SR_rollback, + wsrep_thd_skip_locking, + wsrep_get_sr_table_name, + wsrep_get_debug }; static struct thd_specifics_service_st thd_specifics_handler= diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index cb822fc2e98..c8cc64dba7e 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -4218,30 +4218,6 @@ reexecute: error= execute(expanded_query, open_cursor) || thd->is_error(); thd->m_reprepare_observer= NULL; -#ifdef WITH_WSREP - - if (WSREP_ON) - { - mysql_mutex_lock(&thd->LOCK_thd_data); - 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; - break; - - case MUST_REPLAY: - (void) wsrep_replay_transaction(thd); - break; - - default: - break; - } - mysql_mutex_unlock(&thd->LOCK_thd_data); - } -#endif /* WITH_WSREP */ if (unlikely(error) && (sql_command_flags[lex->sql_command] & CF_REEXECUTION_FRAGILE) && @@ -4414,30 +4390,6 @@ reexecute: error= execute(expanded_query, open_cursor) || thd->is_error(); thd->m_reprepare_observer= NULL; -#ifdef WITH_WSREP - - if (WSREP_ON) - { - mysql_mutex_lock(&thd->LOCK_thd_data); - 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; - break; - - case MUST_REPLAY: - (void) wsrep_replay_transaction(thd); - break; - - default: - break; - } - mysql_mutex_unlock(&thd->LOCK_thd_data); - } -#endif /* WITH_WSREP */ if (unlikely(error) && (sql_command_flags[lex->sql_command] & CF_REEXECUTION_FRAGILE) && 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 f200f6f8c6d..11cfce172c5 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2611,9 +2611,6 @@ err: /* Chop of the last comma */ built_non_trans_tmp_query.chop(); built_non_trans_tmp_query.append(" /* generated by server */"); -#ifdef WITH_WSREP - thd->wsrep_skip_wsrep_GTID = true; -#endif /* WITH_WSREP */ error |= thd->binlog_query(THD::STMT_QUERY_TYPE, built_non_trans_tmp_query.ptr(), built_non_trans_tmp_query.length(), @@ -2626,9 +2623,6 @@ err: /* Chop of the last comma */ built_trans_tmp_query.chop(); built_trans_tmp_query.append(" /* generated by server */"); -#ifdef WITH_WSREP - thd->wsrep_skip_wsrep_GTID = true; -#endif /* WITH_WSREP */ error |= thd->binlog_query(THD::STMT_QUERY_TYPE, built_trans_tmp_query.ptr(), built_trans_tmp_query.length(), @@ -2643,9 +2637,6 @@ err: built_query.append(" /* generated by server */"); int error_code = non_tmp_error ? thd->get_stmt_da()->sql_errno() : 0; -#ifdef WITH_WSREP - thd->wsrep_skip_wsrep_GTID = false; -#endif /* WITH_WSREP */ error |= thd->binlog_query(THD::STMT_QUERY_TYPE, built_query.ptr(), built_query.length(), @@ -2694,9 +2685,6 @@ err: } end: -#ifdef WITH_WSREP - thd->wsrep_skip_wsrep_GTID = false; -#endif /* WITH_WSREP */ DBUG_RETURN(error); } diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index b79c1a1adb1..33af220ae67 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -507,8 +507,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) } #ifdef WITH_WSREP - if (thd->wsrep_exec_mode == LOCAL_STATE) - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); #endif /* We should have only one table in table list. */ diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index 798e929170c..389276d0bcf 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -416,9 +416,11 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref) { bool hton_can_recreate; +#ifdef WITH_WSREP if (WSREP(thd) && wsrep_to_isolation_begin(thd, table_ref->db.str, table_ref->table_name.str, 0)) DBUG_RETURN(TRUE); +#endif /* WITH_WSREP */ if (lock_table(thd, table_ref, &hton_can_recreate)) DBUG_RETURN(TRUE); diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 37b3d65e20a..df681e31d19 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -5519,7 +5519,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)); @@ -5539,12 +5539,48 @@ 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_ulonglong 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), + ON_UPDATE(wsrep_trx_fragment_size_update)); + +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, " + "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(wsrep_trx_fragment_unit_update)); + +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 488d05b1a22..01f96b5f93b 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -247,6 +247,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, "mysql") == 0 && + my_strcasecmp(system_charset_info, name->str, "wsrep_streaming_log") == 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 13614d36a73..4d61d2a120d 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -24,6 +24,9 @@ #include "debug_sync.h" // DEBUG_SYNC #include "sql_acl.h" #include "semisync_master.h" +#ifdef WITH_WSREP +#include "wsrep_trans_observer.h" +#endif /* WITH_WSREP */ #ifndef EMBEDDED_LIBRARY /** @@ -135,8 +138,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 +185,16 @@ 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); +#ifdef WITH_WSREP + if (wsrep_thd_is_local(thd)) + { + res= res || wsrep_after_statement(thd); + } +#endif /* WITH_WSREP */ } thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); @@ -252,9 +255,14 @@ 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); + if (wsrep_thd_is_local(thd)) + { + if (wsrep_sync_wait(thd)) + DBUG_RETURN(TRUE); + if (!thd->tx_read_only && + wsrep_start_transaction(thd, thd->wsrep_next_trx_id())) + DBUG_RETURN(TRUE); + } #endif /* WITH_WSREP */ thd->variables.option_bits|= OPTION_BEGIN; @@ -299,8 +307,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 +317,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 +372,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 +409,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")); @@ -515,14 +510,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 +569,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 +722,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 +934,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 +955,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 1f50ee55711..2c4dab3bd20 100644 --- a/sql/wsrep_applier.cc +++ b/sql/wsrep_applier.cc @@ -14,12 +14,17 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "mariadb.h" +#include "mysql/service_wsrep.h" +#include "wsrep_applier.h" + #include "wsrep_priv.h" #include "wsrep_binlog.h" // wsrep_dump_rbr_buf() #include "wsrep_xid.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" /* @@ -27,7 +32,6 @@ At the end (*buf) is shitfed to point to the following event or NULL and (*buf_len) will be changed to account just being read bytes of the 1st event. */ - static Log_event* wsrep_read_log_event( char **arg_buf, size_t *arg_buf_len, const Format_description_log_event *description_event) @@ -35,7 +39,7 @@ static Log_event* wsrep_read_log_event( DBUG_ENTER("wsrep_read_log_event"); char *head= (*arg_buf); - uint data_len = uint4korr(head + EVENT_LEN_OFFSET); + uint data_len= uint4korr(head + EVENT_LEN_OFFSET); char *buf= (*arg_buf); const char *error= 0; Log_event *res= 0; @@ -62,12 +66,13 @@ 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; } -Format_description_log_event* wsrep_get_apply_format(THD* thd) +Format_description_log_event* +wsrep_get_apply_format(THD* thd) { if (thd->wsrep_apply_format) { @@ -79,45 +84,77 @@ 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) { - char *buf= (char *)events_buf; - int rcode= 0; - int event= 1; - Log_event_type typ; + Diagnostics_area::Sql_condition_iterator it= + thd->get_stmt_da()->sql_conditions(); + const Sql_condition* cond; - DBUG_ENTER("wsrep_apply_events"); + 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 */ + } - if (thd->killed == KILL_CONNECTION && - thd->wsrep_conflict_state != REPLAYING) + 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++) { - WSREP_INFO("applier has been aborted, skipping apply_rbr: %lld", - (long long) wsrep_thd_trx_seqno(thd)); - DBUG_RETURN(WSREP_CB_FAILURE); + 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); } - 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); + *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, + Relay_log_info* rli, + const void* events_buf, + size_t buf_len) +{ + char *buf= (char *)events_buf; + int rcode= 0; + int event= 1; + Log_event_type typ; + DBUG_ENTER("wsrep_apply_events"); if (!buf_len) WSREP_DEBUG("empty rbr buffer to apply: %lld", (long long) wsrep_thd_trx_seqno(thd)); - while(buf_len) + while (buf_len) { int exec_res; Log_event* ev= wsrep_read_log_event(&buf, &buf_len, - wsrep_get_apply_format(thd)); - + wsrep_get_apply_format(thd)); if (!ev) { 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; } @@ -147,9 +184,12 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, thd->set_server_id(ev->server_id); thd->set_time(); // time the query thd->transaction.start_time.reset(thd); + //#define mariadb_10_4_0 +#ifdef mariadb_10_4_0 wsrep_xid_init(&thd->transaction.xid_state.xid, thd->wsrep_trx_meta.gtid.uuid, thd->wsrep_trx_meta.gtid.seqno); +#endif thd->lex->current_select= 0; if (!ev->when) { @@ -162,13 +202,13 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, (thd->variables.option_bits & ~OPTION_SKIP_REPLICATION) | (ev->flags & LOG_EVENT_SKIP_REPLICATION_F ? OPTION_SKIP_REPLICATION : 0); - ev->thd = thd; - exec_res = ev->apply_event(thd->wsrep_rgi); + ev->thd= thd; + exec_res= ev->apply_event(thd->wsrep_rgi); DBUG_PRINT("info", ("exec_event result: %d", exec_res)); 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; @@ -178,230 +218,14 @@ static wsrep_cb_status_t wsrep_apply_events(THD* thd, } event++; - 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)); - - if (thd->wsrep_conflict_state == MUST_ABORT) { - WSREP_WARN("RBR 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); - } - 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); - +error: 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); -} - -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) -{ - THD* const thd((THD*)ctx); - - assert(thd->wsrep_apply_toi == false); - - // Allow tests to block the applier thread using the DBUG facilities. - DBUG_EXECUTE_IF("sync.wsrep_apply_cb", - { - const char act[]= - "now " - "SIGNAL sync.wsrep_apply_cb_reached " - "WAIT_FOR signal.wsrep_apply_cb"; - DBUG_ASSERT(!debug_sync_set_action(thd, - 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) - thd->variables.option_bits|= OPTION_RELAXED_UNIQUE_CHECKS; - else - thd->variables.option_bits&= ~OPTION_RELAXED_UNIQUE_CHECKS; - - 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; - - if (flags & WSREP_FLAG_ISOLATION) - { - 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_cb_status_t rcode(wsrep_apply_events(thd, buf, buf_len)); - -#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 */ - - if (WSREP_CB_SUCCESS != rcode) - { - wsrep_dump_rbr_buf_with_header(thd, buf, buf_len); - } - - if (thd->has_thd_temporary_tables()) - { - WSREP_DEBUG("Applier %lld has temporary tables. Closing them now..", - thd->thread_id); - thd->close_temporary_tables(); - } - - return rcode; -} - -static wsrep_cb_status_t wsrep_commit(THD* const thd) -{ -#ifdef WSREP_PROC_INFO - snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, - "Committing %lld", (long long)wsrep_thd_trx_seqno(thd)); - thd_proc_info(thd, thd->wsrep_info); -#else - thd_proc_info(thd, "Committing"); -#endif /* WSREP_PROC_INFO */ - - wsrep_cb_status_t const rcode(trans_commit(thd) ? - WSREP_CB_FAILURE : WSREP_CB_SUCCESS); - - if (WSREP_CB_SUCCESS == rcode) - { - thd->wsrep_rgi->cleanup_context(thd, false); -#ifdef GTID_SUPPORT - thd->variables.gtid_next.set_automatic(); -#endif /* GTID_SUPPORT */ - if (thd->wsrep_apply_toi) - { - wsrep_set_SE_checkpoint(thd->wsrep_trx_meta.gtid.uuid, - thd->wsrep_trx_meta.gtid.seqno); - } - } - -#ifdef WSREP_PROC_INFO - snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, - "Committed %lld", (long long) wsrep_thd_trx_seqno(thd)); - thd_proc_info(thd, thd->wsrep_info); -#else - thd_proc_info(thd, "Committed"); -#endif /* WSREP_PROC_INFO */ - - return rcode; -} - -static wsrep_cb_status_t wsrep_rollback(THD* const 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 */ - - wsrep_cb_status_t const rcode(trans_rollback(thd) ? - WSREP_CB_FAILURE : WSREP_CB_SUCCESS); - -#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 */ - - return rcode; -} - -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); - - assert(meta->gtid.seqno == wsrep_thd_trx_seqno(thd)); - - wsrep_cb_status_t rcode; - - if (commit) - rcode = wsrep_commit(thd); - else - rcode = wsrep_rollback(thd); - - /* 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) - { - mysql_mutex_lock(&LOCK_wsrep_slave_threads); - if (wsrep_slave_count_change < 0) - { - wsrep_slave_count_change++; - *exit = true; - } - mysql_mutex_unlock(&LOCK_wsrep_slave_threads); - } - - if (thd->wsrep_applier) - { - /* From trans_begin() */ - thd->variables.option_bits|= OPTION_BEGIN; - thd->server_status|= SERVER_STATUS_IN_TRANS; - thd->wsrep_apply_toi= false; - } - - return rcode; -} - - -wsrep_cb_status_t wsrep_unordered_cb(void* const ctx, - const void* const data, - size_t const size) -{ - return WSREP_CB_SUCCESS; + DBUG_RETURN(rcode); } diff --git a/sql/wsrep_applier.h b/sql/wsrep_applier.h index f19d2d46d0c..a8da2acbb9a 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 @@ -17,28 +17,57 @@ #define WSREP_APPLIER_H #include <my_config.h> -#include "../wsrep/wsrep_api.h" -void wsrep_set_apply_format(THD* thd, Format_description_log_event* ev); -Format_description_log_event* wsrep_get_apply_format(THD* thd); +#include "sql_class.h" // THD class + +int wsrep_apply_events(THD* thd, + Relay_log_info* rli, + 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); +/* 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 -wsrep_cb_status_t wsrep_commit_cb(void *ctx, - uint32_t flags, - const wsrep_trx_meta_t* meta, - wsrep_bool_t* exit, - bool commit); +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_; +}; + +class Format_description_log_event; +void wsrep_set_apply_format(THD*, Format_description_log_event*); +Format_description_log_event* wsrep_get_apply_format(THD* thd); +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 0cbcdcd64aa..b02692d14fe 100644 --- a/sql/wsrep_binlog.cc +++ b/sql/wsrep_binlog.cc @@ -14,12 +14,15 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "mariadb.h" +#include "mysql/service_wsrep.h" #include "wsrep_binlog.h" #include "wsrep_priv.h" #include "log.h" #include "log_event.h" #include "wsrep_applier.h" +#include "transaction.h" + extern handlerton *binlog_hton; /* Write the contents of a cache to a memory buffer. @@ -40,10 +43,10 @@ int wsrep_write_cache_buf(IO_CACHE *cache, uchar **buf, size_t *buf_len) DBUG_RETURN(ER_ERROR_ON_WRITE); } - uint length = my_b_bytes_in_cache(cache); - if (unlikely(0 == length)) length = my_b_fill(cache); + uint length= my_b_bytes_in_cache(cache); + if (unlikely(0 == length)) length= my_b_fill(cache); - size_t total_length = 0; + size_t total_length= 0; if (likely(length > 0)) do { @@ -60,7 +63,7 @@ int wsrep_write_cache_buf(IO_CACHE *cache, uchar **buf, size_t *buf_len) wsrep_max_ws_size, total_length); goto error; } - uchar* tmp = (uchar *)my_realloc(*buf, total_length, + uchar* tmp= (uchar *)my_realloc(*buf, total_length, MYF(MY_ALLOW_ZERO_PTR)); if (!tmp) { @@ -68,17 +71,17 @@ int wsrep_write_cache_buf(IO_CACHE *cache, uchar **buf, size_t *buf_len) *buf_len, length); goto error; } - *buf = tmp; + *buf= tmp; memcpy(*buf + *buf_len, cache->read_pos, length); - *buf_len = total_length; + *buf_len= total_length; if (cache->file < 0) { cache->read_pos= cache->read_end; break; } - } while ((length = my_b_fill(cache))); + } while ((length= my_b_fill(cache))); if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0)) { @@ -111,130 +114,6 @@ heap_size(size_t length) return (length + HEAP_PAGE_SIZE - 1)/HEAP_PAGE_SIZE*HEAP_PAGE_SIZE; } -/* append data to writeset */ -static inline wsrep_status_t -wsrep_append_data(wsrep_t* const wsrep, - wsrep_ws_handle_t* const ws, - const void* const data, - size_t const len) -{ - struct wsrep_buf const buff = { data, len }; - wsrep_status_t const rc(wsrep->append_data(wsrep, ws, &buff, 1, - WSREP_DATA_ORDERED, true)); - DBUG_DUMP("buff", (uchar*) data, len); - if (rc != WSREP_OK) - { - WSREP_WARN("append_data() returned %d", rc); - } - - return rc; -} - -/* - Write the contents of a cache to wsrep provider. - - This function quite the same as MYSQL_BIN_LOG::write_cache(), - with the exception that here we write in buffer instead of log file. - - 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) -{ - 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)) - { - WSREP_ERROR("failed to initialize io-cache"); - DBUG_RETURN(ER_ERROR_ON_WRITE); - } - - int err(WSREP_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); - - uint length(my_b_bytes_in_cache(cache)); - if (unlikely(0 == length)) length = my_b_fill(cache); - - if (likely(length > 0)) do - { - total_length += length; - /* - Bail out if buffer grows too large. - A temporary fix to avoid allocating indefinitely large buffer, - not a real limit on a writeset size which includes other things - like header and keys. - */ - if (unlikely(total_length > wsrep_max_ws_size)) - { - WSREP_WARN("transaction size limit (%lu) exceeded: %zu", - wsrep_max_ws_size, total_length); - err = 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)); - if (!tmp) - { - WSREP_ERROR("could not (re)allocate buffer: %zu + %u", - allocated, length); - err = WSREP_TRX_SIZE_EXCEEDED; - goto cleanup; - } - - heap_buf = tmp; - buf = heap_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(buf + used, cache->read_pos, length); - used = total_length; - if (cache->file < 0) - { - cache->read_pos= cache->read_end; - break; - } - } while ((length = my_b_fill(cache))); - - if (used > 0) - err = wsrep_append_data(wsrep, &thd->wsrep_ws_handle, buf, used); - - if (WSREP_OK == err) *len = total_length; - -cleanup: - if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0)) - { - WSREP_ERROR("failed to reinitialize io-cache"); - } - - if (unlikely(WSREP_OK != err)) - { - wsrep_dump_rbr_buf_with_header(thd, buf, used); - } - - my_free(heap_buf); - DBUG_RETURN(err); -} - /* Write the contents of a cache to wsrep provider. @@ -243,62 +122,58 @@ 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, +static int wsrep_write_cache_inc(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)) - { - WSREP_ERROR("failed to initialize io-cache"); - DBUG_RETURN(WSREP_TRX_ERROR); - } + DBUG_ENTER("wsrep_write_cache_inc"); + my_off_t const saved_pos(my_b_tell(cache)); - int err(WSREP_OK); + if (reinit_io_cache(cache, READ_CACHE, thd->wsrep_sr().bytes_certified(), 0, 0)) + { + WSREP_ERROR("failed to initialize io-cache"); + DBUG_RETURN(1);; + } - size_t total_length(0); + int ret= 0; + size_t total_length(0); - uint length(my_b_bytes_in_cache(cache)); - if (unlikely(0 == length)) length = my_b_fill(cache); + uint length(my_b_bytes_in_cache(cache)); + if (unlikely(0 == length)) length= my_b_fill(cache); - if (likely(length > 0)) do + if (likely(length > 0)) + { + do { - total_length += length; - /* bail out if buffer grows too large - not a real limit on a writeset size which includes other things - like header and keys. - */ - if (unlikely(total_length > wsrep_max_ws_size)) - { - WSREP_WARN("transaction size limit (%lu) exceeded: %zu", - wsrep_max_ws_size, total_length); - err = WSREP_TRX_SIZE_EXCEEDED; - goto cleanup; - } - - if(WSREP_OK != (err=wsrep_append_data(wsrep, &thd->wsrep_ws_handle, - cache->read_pos, length))) - goto cleanup; - - if (cache->file < 0) - { - cache->read_pos= cache->read_end; - break; - } - } while ((length = my_b_fill(cache))); - - if (WSREP_OK == err) *len = total_length; + total_length += length; + /* bail out if buffer grows too large + not a real limit on a writeset size which includes other things + like header and keys. + */ + if (unlikely(total_length > wsrep_max_ws_size)) + { + WSREP_WARN("transaction size limit (%lu) exceeded: %zu", + wsrep_max_ws_size, total_length); + ret= 1; + goto cleanup; + } + if (thd->wsrep_cs().append_data(wsrep::const_buffer(cache->read_pos, length))) + goto cleanup; + cache->read_pos= cache->read_end; + } while ((cache->file >= 0) && (length= my_b_fill(cache))); + } + if (ret == 0) + { + assert(total_length + thd->wsrep_sr().bytes_certified() == saved_pos); + } cleanup: - if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0)) - { - WSREP_ERROR("failed to reinitialize io-cache"); - } - - DBUG_RETURN(err); + *len= total_length; + if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0)) + { + WSREP_ERROR("failed to reinitialize io-cache"); + } + DBUG_RETURN(ret); } /* @@ -307,17 +182,11 @@ 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, +int wsrep_write_cache(THD* const thd, IO_CACHE* const cache, size_t* const len) { - if (wsrep_incremental_data_collection) { - return wsrep_write_cache_inc(wsrep, thd, cache, len); - } - else { - return wsrep_write_cache_once(wsrep, thd, cache, len); - } + return wsrep_write_cache_inc(thd, cache, len); } void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len) @@ -383,80 +252,17 @@ int wsrep_binlog_close_connection(THD* thd) int wsrep_binlog_savepoint_set(THD *thd, void *sv) { if (!wsrep_emulate_bin_log) return 0; - int rcode = binlog_hton->savepoint_set(binlog_hton, thd, sv); + int rcode= binlog_hton->savepoint_set(binlog_hton, thd, sv); return rcode; } int wsrep_binlog_savepoint_rollback(THD *thd, void *sv) { if (!wsrep_emulate_bin_log) return 0; - int rcode = binlog_hton->savepoint_rollback(binlog_hton, thd, sv); + int rcode= binlog_hton->savepoint_rollback(binlog_hton, thd, sv); return rcode; } -#if 0 -void wsrep_dump_rbr_direct(THD* thd, IO_CACHE* cache) -{ - char filename[PATH_MAX]= {0}; - int len= snprintf(filename, PATH_MAX, "%s/GRA_%lld_%lld.log", - wsrep_data_home_dir, (longlong) thd->thread_id, - (longlong) wsrep_thd_trx_seqno(thd)); - size_t bytes_in_cache = 0; - // check path - if (len >= PATH_MAX) - { - WSREP_ERROR("RBR dump path too long: %d, skipping dump.", len); - return ; - } - // init cache - my_off_t const saved_pos(my_b_tell(cache)); - if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0)) - { - WSREP_ERROR("failed to initialize io-cache"); - return ; - } - // open file - FILE* of = fopen(filename, "wb"); - if (!of) - { - WSREP_ERROR("Failed to open file '%s': %d (%s)", - filename, errno, strerror(errno)); - goto cleanup; - } - // ready to write - bytes_in_cache= my_b_bytes_in_cache(cache); - if (unlikely(bytes_in_cache == 0)) bytes_in_cache = my_b_fill(cache); - if (likely(bytes_in_cache > 0)) do - { - if (my_fwrite(of, cache->read_pos, bytes_in_cache, - MYF(MY_WME | MY_NABP)) == (size_t) -1) - { - WSREP_ERROR("Failed to write file '%s'", filename); - goto cleanup; - } - - if (cache->file < 0) - { - cache->read_pos= cache->read_end; - break; - } - } while ((bytes_in_cache= my_b_fill(cache))); - if (cache->error == -1) - { - WSREP_ERROR("RBR inconsistent"); - goto cleanup; - } -cleanup: - // init back - if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0)) - { - WSREP_ERROR("failed to reinitialize io-cache"); - } - // close file - if (of) fclose(of); -} -#endif - void thd_binlog_flush_pending_rows_event(THD *thd, bool stmt_end) { thd->binlog_flush_pending_rows_event(stmt_end); @@ -544,3 +350,31 @@ cleanup1: DBUG_VOID_RETURN; } +#include "log_event.h" + +int wsrep_write_skip_event(THD* thd) +{ + DBUG_ENTER("wsrep_write_skip_event"); + Ignorable_log_event skip_event(thd); + int ret= mysql_bin_log.write_event(&skip_event); + if (ret) + { + WSREP_WARN("wsrep_write_skip_event: write to binlog failed: %d", ret); + } + if (!ret && (ret= trans_commit_stmt(thd))) + { + WSREP_WARN("wsrep_write_skip_event: statt commit failed"); + } + DBUG_RETURN(ret); +} + +int wsrep_write_dummy_event_low(THD *thd, const char *msg) +{ + ::abort(); + return 0; +} + +int wsrep_write_dummy_event(THD *orig_thd, const char *msg) +{ + return 0; +} diff --git a/sql/wsrep_binlog.h b/sql/wsrep_binlog.h index 864813d5c98..4cef38c85d3 100644 --- a/sql/wsrep_binlog.h +++ b/sql/wsrep_binlog.h @@ -16,6 +16,7 @@ #ifndef WSREP_BINLOG_H #define WSREP_BINLOG_H +#include "my_global.h" #include "sql_class.h" // THD, IO_CACHE #define HEAP_PAGE_SIZE 65536 /* 64K */ @@ -38,23 +39,39 @@ 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); +int wsrep_write_cache(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); + +/** + Write a skip event into binlog. + + @param thd Thread object pointer + @return Zero in case of success, non-zero on failure. +*/ +int wsrep_write_skip_event(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_check_opts.cc b/sql/wsrep_check_opts.cc index 0b7a9ca6252..7b8067ef238 100644 --- a/sql/wsrep_check_opts.cc +++ b/sql/wsrep_check_opts.cc @@ -33,7 +33,7 @@ int wsrep_check_opts() autoinc_lock_mode->val_int(&is_null, 0, OPT_GLOBAL, 0) != 2) { WSREP_ERROR("Parallel applying (wsrep_slave_threads > 1) requires" - " innodb_autoinc_lock_mode = 2."); + " innodb_autoinc_lock_mode= 2."); return 1; } } @@ -88,7 +88,7 @@ int wsrep_check_opts() { if (global_system_variables.binlog_format != BINLOG_FORMAT_ROW) { - WSREP_ERROR("Only binlog_format = 'ROW' is currently supported. " + WSREP_ERROR("Only binlog_format= 'ROW' is currently supported. " "Configured value: '%s'. Please adjust your " "configuration.", binlog_format_names[global_system_variables.binlog_format]); diff --git a/sql/wsrep_client_service.cc b/sql/wsrep_client_service.cc new file mode 100644 index 00000000000..994fa97db60 --- /dev/null +++ b/sql/wsrep_client_service.cc @@ -0,0 +1,307 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "wsrep_client_service.h" +#include "wsrep_high_priority_service.h" +#include "wsrep_applier.h" /* wsrep_apply_events() */ +#include "wsrep_binlog.h" /* wsrep_dump_rbr_buf() */ +#include "wsrep_schema.h" /* remove_fragments() */ +#include "wsrep_thd.h" +#include "wsrep_xid.h" +#include "wsrep_trans_observer.h" + +#include "sql_base.h" /* close_temporary_table() */ +#include "sql_class.h" /* THD */ +#include "sql_parse.h" /* stmt_causes_implicit_commit() */ +#include "rpl_filter.h" /* binlog_filter */ +#include "rpl_rli.h" /* Relay_log_info */ +#include "slave.h" /* opt_log_slave_updates */ +#include "transaction.h" /* trans_commit()... */ +#include "log.h" /* stmt_has_updated_trans_table() */ +//#include "debug_sync.h" +#include "mysql/service_debug_sync.h" +namespace +{ + +void debug_sync_caller(THD* thd, const char* sync_point) +{ +#ifdef ENABLED_DEBUG_SYNC_OUT + debug_sync_set_action(thd, sync_point, strlen(sync_point)); +#endif +#ifdef ENABLED_DEBUG_SYNC + if (debug_sync_service) debug_sync_service(thd,sync_point,strlen(sync_point)); +#endif + +} +} + +Wsrep_client_service::Wsrep_client_service(THD* thd, + Wsrep_client_state& client_state) + : wsrep::client_service() + , m_thd(thd) + , m_client_state(client_state) +{ } + +void Wsrep_client_service::store_globals() +{ + DBUG_ENTER("Wsrep_client_service::store_globals"); + m_thd->store_globals(); + DBUG_VOID_RETURN; +} + +void Wsrep_client_service::reset_globals() +{ + DBUG_ENTER("Wsrep_client_service::reset_globals"); + m_thd->reset_globals(); + DBUG_VOID_RETURN; +} + +bool Wsrep_client_service::interrupted() const +{ + DBUG_ASSERT(m_thd == current_thd); + mysql_mutex_lock(&m_thd->LOCK_thd_data); + + /* wsrep state can be interrupted only if THD was explicitly killed, + for wsrep conflicts, we use deadlock error only + */ + bool ret= (m_thd->killed != NOT_KILLED && + m_thd->wsrep_trx().state() != wsrep::transaction::s_must_abort && + m_thd->wsrep_trx().state() != wsrep::transaction::s_aborting && + m_thd->wsrep_trx().state() != wsrep::transaction::s_aborted); + mysql_mutex_unlock(&m_thd->LOCK_thd_data); + if (ret) + { + WSREP_DEBUG("wsrep state is interrupted, THD::killed %d trx state %d", + m_thd->killed, m_thd->wsrep_trx().state()); + } + return ret; +} + +int Wsrep_client_service::prepare_data_for_replication() +{ + DBUG_ASSERT(m_thd == current_thd); + DBUG_ENTER("Wsrep_client_service::prepare_data_for_replication"); + size_t data_len= 0; + IO_CACHE* cache= wsrep_get_trans_cache(m_thd); + + if (cache) + { + m_thd->binlog_flush_pending_rows_event(true); + if (wsrep_write_cache(m_thd, cache, &data_len)) + { + WSREP_ERROR("rbr write fail, data_len: %zu", + data_len); + // wsrep_override_error(m_thd, ER_ERROR_DURING_COMMIT); + DBUG_RETURN(1); + } + } + + if (data_len == 0) + { + if (m_thd->get_stmt_da()->is_ok() && + m_thd->get_stmt_da()->affected_rows() > 0 && + !binlog_filter->is_on() && + !m_thd->wsrep_trx().is_streaming()) + { + WSREP_DEBUG("empty rbr buffer, query: %s, " + "affected rows: %llu, " + "changed tables: %d, " + "sql_log_bin: %d", + WSREP_QUERY(m_thd), + m_thd->get_stmt_da()->affected_rows(), + stmt_has_updated_trans_table(m_thd), + m_thd->variables.sql_log_bin); + } + else + { + WSREP_DEBUG("empty rbr buffer, query: %s", WSREP_QUERY(m_thd)); + } + } + DBUG_RETURN(0); +} + + +void Wsrep_client_service::cleanup_transaction() +{ + DBUG_ASSERT(m_thd == current_thd); + if (WSREP_EMULATE_BINLOG(m_thd)) wsrep_thd_binlog_trx_reset(m_thd); + m_thd->wsrep_affected_rows= 0; +} + + +int Wsrep_client_service::prepare_fragment_for_replication(wsrep::mutable_buffer& buffer) +{ + DBUG_ASSERT(m_thd == current_thd); + THD* thd= m_thd; + DBUG_ENTER("Wsrep_client_service::prepare_fragment_for_replication"); + IO_CACHE* cache= wsrep_get_trans_cache(thd); + thd->binlog_flush_pending_rows_event(true); + + if (!cache) + { + DBUG_RETURN(0); + } + + const my_off_t saved_pos(my_b_tell(cache)); + if (reinit_io_cache(cache, READ_CACHE, thd->wsrep_sr().bytes_certified(), 0, 0)) + { + DBUG_RETURN(1); + } + + int ret= 0; + size_t total_length= 0; + size_t length= my_b_bytes_in_cache(cache); + + if (!length) + { + length= my_b_fill(cache); + } + + if (length > 0) + { + do + { + total_length+= length; + if (total_length > wsrep_max_ws_size) + { + WSREP_WARN("transaction size limit (%lu) exceeded: %zu", + wsrep_max_ws_size, total_length); + ret= 1; + goto cleanup; + } + + buffer.push_back(reinterpret_cast<const char*>(cache->read_pos), + reinterpret_cast<const char*>(cache->read_pos + length)); + cache->read_pos= cache->read_end; + } + while (cache->file >= 0 && (length= my_b_fill(cache))); + } + DBUG_ASSERT(total_length == buffer.size()); +cleanup: + if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0)) + { + WSREP_WARN("Failed to reinitialize IO cache"); + ret= 1; + } + DBUG_RETURN(ret); +} + +int Wsrep_client_service::remove_fragments() +{ + DBUG_ENTER("Wsrep_client_service::remove_fragments"); + if (wsrep_schema->remove_fragments(m_thd, + Wsrep_server_state::instance().id(), + m_thd->wsrep_trx().id(), + m_thd->wsrep_sr().fragments())) + { + WSREP_DEBUG("Failed to remove fragments from SR storage for transaction " + "%llu, %llu", + m_thd->thread_id, m_thd->wsrep_trx().id().get()); + DBUG_RETURN(1); + } + DBUG_RETURN(0); +} + +bool Wsrep_client_service::statement_allowed_for_streaming() const +{ + /* + Todo: Decide if implicit commit is allowed with streaming + replication. + !stmt_causes_implicit_commit(m_thd, CF_IMPLICIT_COMMIT_BEGIN); + */ + return true; +} + +size_t Wsrep_client_service::bytes_generated() const +{ + IO_CACHE* cache= wsrep_get_trans_cache(m_thd); + if (cache) + { + m_thd->binlog_flush_pending_rows_event(true); + return my_b_tell(cache); + } + return 0; +} + +void Wsrep_client_service::will_replay() +{ + DBUG_ASSERT(m_thd == current_thd); + mysql_mutex_lock(&LOCK_wsrep_replaying); + ++wsrep_replaying; + mysql_mutex_unlock(&LOCK_wsrep_replaying); +} + +enum wsrep::provider::status Wsrep_client_service::replay() +{ + DBUG_ASSERT(m_thd == current_thd); + Wsrep_replayer_service replayer_service(m_thd); + wsrep::provider& provider(m_thd->wsrep_cs().provider()); + mysql_mutex_lock(&m_thd->LOCK_thd_data); + m_thd->killed= NOT_KILLED; + mysql_mutex_unlock(&m_thd->LOCK_thd_data); + enum wsrep::provider::status ret= + provider.replay(m_thd->wsrep_trx().ws_handle(), &replayer_service); + replayer_service.replay_status(ret); + mysql_mutex_lock(&LOCK_wsrep_replaying); + --wsrep_replaying; + mysql_mutex_unlock(&LOCK_wsrep_replaying); + return ret; +} + +void Wsrep_client_service::wait_for_replayers(wsrep::unique_lock<wsrep::mutex>& lock) +{ + DBUG_ASSERT(m_thd == current_thd); + lock.unlock(); + mysql_mutex_lock(&LOCK_wsrep_replaying); + while (wsrep_replaying > 0) + { + mysql_cond_wait(&COND_wsrep_replaying, &LOCK_wsrep_replaying); + } + mysql_mutex_unlock(&LOCK_wsrep_replaying); + lock.lock(); +} + +void Wsrep_client_service::debug_sync(const char* sync_point) +{ + DBUG_ASSERT(m_thd == current_thd); + debug_sync_caller(m_thd, sync_point); +} + +void Wsrep_client_service::debug_crash(const char* crash_point) +{ + // DBUG_ASSERT(m_thd == current_thd); + DBUG_EXECUTE_IF(crash_point, DBUG_SUICIDE(); ); +} + +int Wsrep_client_service::bf_rollback() +{ + DBUG_ASSERT(m_thd == current_thd); + DBUG_ENTER("Wsrep_client_service::rollback"); + + int ret= (trans_rollback_stmt(m_thd) || trans_rollback(m_thd)); + if (m_thd->locked_tables_mode && m_thd->lock) + { + m_thd->locked_tables_list.unlock_locked_tables(m_thd); + m_thd->variables.option_bits&= ~OPTION_TABLE_LOCK; + } + if (m_thd->global_read_lock.is_acquired()) + { + m_thd->global_read_lock.unlock_global_read_lock(m_thd); + } + m_thd->mdl_context.release_transactional_locks(); + m_thd->mdl_context.release_explicit_locks(); + + DBUG_RETURN(ret); +} diff --git a/sql/wsrep_client_service.h b/sql/wsrep_client_service.h new file mode 100644 index 00000000000..43edae3441d --- /dev/null +++ b/sql/wsrep_client_service.h @@ -0,0 +1,63 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +/** @file wsrep_client_service.h + + This file provides declaratios for client service implementation. + See wsrep/client_service.hpp for interface documentation. +*/ + +#ifndef WSREP_CLIENT_SERVICE_H +#define WSREP_CLIENT_SERVICE_H + +/* wsrep-lib */ +#include "wsrep/client_service.hpp" +#include "wsrep/client_state.hpp" +#include "wsrep/exception.hpp" /* not_implemented_error, remove when finished */ + +class THD; +class Wsrep_client_state; +class Wsrep_high_priority_context; + +class Wsrep_client_service : public wsrep::client_service +{ +public: + Wsrep_client_service(THD*, Wsrep_client_state&); + + bool interrupted() const; + void reset_globals(); + void store_globals(); + int prepare_data_for_replication(); + void cleanup_transaction(); + bool statement_allowed_for_streaming() const; + size_t bytes_generated() const; + int prepare_fragment_for_replication(wsrep::mutable_buffer&); + int remove_fragments(); + void emergency_shutdown() + { throw wsrep::not_implemented_error(); } + void will_replay(); + enum wsrep::provider::status replay(); + void wait_for_replayers(wsrep::unique_lock<wsrep::mutex>&); + void debug_sync(const char*); + void debug_crash(const char*); + int bf_rollback(); +private: + friend class Wsrep_server_service; + THD* m_thd; + Wsrep_client_state& m_client_state; +}; + + +#endif /* WSREP_CLIENT_SERVICE_H */ diff --git a/sql/wsrep_client_state.h b/sql/wsrep_client_state.h new file mode 100644 index 00000000000..403bfa81365 --- /dev/null +++ b/sql/wsrep_client_state.h @@ -0,0 +1,47 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef WSREP_CLIENT_STATE_H +#define WSREP_CLIENT_STATE_H + +/* wsrep-lib */ +#include "wsrep/client_state.hpp" +#include "my_global.h" + +class THD; + +class Wsrep_client_state : public wsrep::client_state +{ +public: + Wsrep_client_state(THD* thd, + wsrep::mutex& mutex, + wsrep::condition_variable& cond, + wsrep::server_state& server_state, + wsrep::client_service& client_service, + const wsrep::client_id& id) + : wsrep::client_state(mutex, + cond, + server_state, + client_service, + id, + wsrep::client_state::m_local) + , m_thd(thd) + { } + THD* thd() { return m_thd; } +private: + THD* m_thd; +}; + +#endif /* WSREP_CLIENT_STATE_H */ diff --git a/sql/wsrep_condition_variable.h b/sql/wsrep_condition_variable.h new file mode 100644 index 00000000000..4412154e67b --- /dev/null +++ b/sql/wsrep_condition_variable.h @@ -0,0 +1,54 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef WSREP_CONDITION_VARIABLE_H +#define WSREP_CONDITION_VARIABLE_H + +/* wsrep-lib */ +#include "wsrep/condition_variable.hpp" + +/* implementation */ +#include "my_pthread.h" + +class Wsrep_condition_variable : public wsrep::condition_variable +{ +public: + + Wsrep_condition_variable(mysql_cond_t& cond) + : m_cond(cond) + { } + ~Wsrep_condition_variable() + { } + + void notify_one() + { + mysql_cond_signal(&m_cond); + } + + void notify_all() + { + mysql_cond_broadcast(&m_cond); + } + + void wait(wsrep::unique_lock<wsrep::mutex>& lock) + { + mysql_mutex_t* mutex= static_cast<mysql_mutex_t*>(lock.mutex().native()); + mysql_cond_wait(&m_cond, mutex); + } +private: + mysql_cond_t& m_cond; +}; + +#endif /* WSREP_CONDITION_VARIABLE_H */ diff --git a/sql/wsrep_dummy.cc b/sql/wsrep_dummy.cc index 9a4bbd01bcd..916788483ab 100644 --- a/sql/wsrep_dummy.cc +++ b/sql/wsrep_dummy.cc @@ -17,16 +17,10 @@ #include <sql_class.h> #include <mysql/service_wsrep.h> -my_bool wsrep_thd_is_BF(THD *, my_bool) +my_bool wsrep_thd_is_BF(const THD *, my_bool) { return 0; } -int wsrep_trx_order_before(THD *, THD *) -{ return 0; } - -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 void* xid) { return 0; } long long wsrep_xid_seqno(const XID* x) @@ -34,111 +28,99 @@ long long wsrep_xid_seqno(const XID* x) const unsigned char* wsrep_xid_uuid(const XID*) { - static const unsigned char uuid[16] = {0}; + static const unsigned char uuid[16]= {0}; return uuid; } +bool wsrep_prepare_key_for_innodb(THD* thd, const uchar*, size_t, const uchar*, size_t, struct wsrep_buf*, size_t*) +{ return 1; } + bool wsrep_prepare_key(const uchar*, size_t, const uchar*, size_t, struct wsrep_buf*, size_t*) { return 0; } struct wsrep *get_wsrep() { return 0; } -my_bool get_wsrep_certify_nonPK() -{ return 0; } - -my_bool get_wsrep_debug() -{ return 0; } - -my_bool get_wsrep_drupal_282555_workaround() -{ return 0; } - -my_bool get_wsrep_load_data_splitting() -{ return 0; } - my_bool get_wsrep_recovery() { return 0; } -my_bool get_wsrep_log_conflicts() -{ return 0; } - -long get_wsrep_protocol_version() -{ return 0; } - -my_bool wsrep_aborting_thd_contains(THD *) -{ return 0; } - -void wsrep_aborting_thd_enqueue(THD *) -{ } - bool wsrep_consistency_check(THD *) { return 0; } void wsrep_lock_rollback() { } -int wsrep_on(THD *thd) +my_bool wsrep_on(const THD *) { return 0; } -void wsrep_post_commit(THD*, bool) -{ } - -enum wsrep_trx_status wsrep_run_wsrep_commit(THD *, bool) -{ return WSREP_TRX_ERROR; } - -void wsrep_thd_LOCK(THD *) -{ } - -void wsrep_thd_UNLOCK(THD *) +void wsrep_thd_LOCK(const THD *) { } -void wsrep_thd_awake(THD *, my_bool) +void wsrep_thd_UNLOCK(const THD *) { } const char *wsrep_thd_conflict_state_str(THD *) { return 0; } -enum wsrep_exec_mode wsrep_thd_exec_mode(THD *) -{ return LOCAL_STATE; } - const char *wsrep_thd_exec_mode_str(THD *) { return NULL; } -enum wsrep_conflict_state wsrep_thd_get_conflict_state(THD *) -{ return NO_CONFLICT; } +const char *wsrep_thd_query(const THD *) +{ return 0; } -my_bool wsrep_thd_is_wsrep(THD *) +const char *wsrep_thd_query_state_str(THD *) { return 0; } -char *wsrep_thd_query(THD *) +int wsrep_thd_retry_counter(const THD *) { return 0; } -enum wsrep_query_state wsrep_thd_query_state(THD *) -{ return QUERY_IDLE; } +bool wsrep_thd_ignore_table(THD *) +{ return 0; } -const char *wsrep_thd_query_state_str(THD *) +long long wsrep_thd_trx_seqno(const THD *) +{ return -1; } + +my_bool wsrep_thd_is_aborting(const THD *) { return 0; } -int wsrep_thd_retry_counter(THD *) +void wsrep_set_data_home_dir(const char *) +{ } + +my_bool wsrep_thd_is_local(const THD *) { return 0; } -void wsrep_thd_set_conflict_state(THD *, enum wsrep_conflict_state) +void wsrep_thd_self_abort(THD *) { } -bool wsrep_thd_ignore_table(THD *) +int wsrep_thd_append_key(THD *, const struct wsrep_key*, int, enum Wsrep_service_key_type) { return 0; } -longlong wsrep_thd_trx_seqno(THD *) -{ return -1; } +const char* wsrep_thd_client_state_str(const THD*) +{ return 0; } -struct wsrep_ws_handle* wsrep_thd_ws_handle(THD *) +const char* wsrep_thd_client_mode_str(const THD*) { return 0; } -int wsrep_trx_is_aborting(THD *) +const char* wsrep_thd_transaction_state_str(const THD*) { return 0; } -void wsrep_unlock_rollback() -{ } +query_id_t wsrep_thd_transaction_id(const THD *) +{ return 0; } -void wsrep_set_data_home_dir(const char *) +my_bool wsrep_thd_bf_abort(const THD *, THD *, my_bool) +{ return 0; } + +my_bool wsrep_thd_order_before(const THD*, const THD *) +{ return 0; } + +void wsrep_handle_SR_rollback(THD*, THD*) { } + +my_bool wsrep_thd_skip_locking(const THD*) +{ return 0;} + +const char* wsrep_get_sr_table_name() +{ return 0; } + +my_bool wsrep_get_debug() +{ return 0;} diff --git a/sql/wsrep_high_priority_service.cc b/sql/wsrep_high_priority_service.cc new file mode 100644 index 00000000000..f1637e2ece0 --- /dev/null +++ b/sql/wsrep_high_priority_service.cc @@ -0,0 +1,649 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "wsrep_high_priority_service.h" +#include "wsrep_applier.h" +#include "wsrep_binlog.h" +#include "wsrep_schema.h" +#include "wsrep_xid.h" +#include "wsrep_trans_observer.h" + +#include "sql_class.h" /* THD */ +#include "transaction.h" +#include "debug_sync.h" +/* RLI */ +#include "rpl_rli.h" +#define NUMBER_OF_FIELDS_TO_IDENTIFY_COORDINATOR 1 +#define NUMBER_OF_FIELDS_TO_IDENTIFY_WORKER 2 +#include "slave.h" +#include "rpl_mi.h" + +namespace +{ +/* + Scoped mode for applying non-transactional write sets (TOI) + */ +class Wsrep_non_trans_mode +{ +public: + Wsrep_non_trans_mode(THD* thd, const wsrep::ws_meta& ws_meta) + : m_thd(thd) + , m_option_bits(thd->variables.option_bits) + , m_server_status(thd->server_status) + { + m_thd->variables.option_bits&= ~OPTION_BEGIN; + m_thd->server_status&= ~SERVER_STATUS_IN_TRANS; + m_thd->wsrep_cs().enter_toi(ws_meta); + } + ~Wsrep_non_trans_mode() + { + m_thd->variables.option_bits= m_option_bits; + m_thd->server_status= m_server_status; + m_thd->wsrep_cs().leave_toi(); + } +private: + Wsrep_non_trans_mode(const Wsrep_non_trans_mode&); + Wsrep_non_trans_mode& operator=(const Wsrep_non_trans_mode&); + THD* m_thd; + ulonglong m_option_bits; + uint m_server_status; +}; +} + +static rpl_group_info* wsrep_relay_group_init(THD* thd, const char* log_fname) +{ + Relay_log_info* rli= new Relay_log_info(false); + + if (!rli->relay_log.description_event_for_exec) + { + rli->relay_log.description_event_for_exec= + new Format_description_log_event(4); + } + + static LEX_CSTRING connection_name= { STRING_WITH_LEN("wsrep") }; + + /* + Master_info's constructor initializes rpl_filter by either an already + constructed Rpl_filter object from global 'rpl_filters' list if the + specified connection name is same, or it constructs a new Rpl_filter + object and adds it to rpl_filters. This object is later destructed by + Mater_info's destructor by looking it up based on connection name in + rpl_filters list. + + However, since all Master_info objects created here would share same + connection name ("wsrep"), destruction of any of the existing Master_info + objects (in wsrep_return_from_bf_mode()) would free rpl_filter referenced + by any/all existing Master_info objects. + + In order to avoid that, we have added a check in Master_info's destructor + to not free the "wsrep" rpl_filter. It will eventually be freed by + free_all_rpl_filters() when server terminates. + */ + rli->mi= new Master_info(&connection_name, false); + + struct rpl_group_info *rgi= new rpl_group_info(rli); + rgi->thd= rli->sql_driver_thd= thd; + + if ((rgi->deferred_events_collecting= rli->mi->rpl_filter->is_on())) + { + rgi->deferred_events= new Deferred_log_events(rli); + } + + return rgi; +} + +static void wsrep_setup_uk_and_fk_checks(THD* thd) +{ + /* Tune FK and UK checking policy. These are reset back to original + in Wsrep_high_priority_service destructor. */ + 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) + thd->variables.option_bits|= OPTION_NO_FOREIGN_KEY_CHECKS; + else + thd->variables.option_bits&= ~OPTION_NO_FOREIGN_KEY_CHECKS; +} + +/**************************************************************************** + High priority service +*****************************************************************************/ + +Wsrep_high_priority_service::Wsrep_high_priority_service(THD* thd) + : wsrep::high_priority_service(Wsrep_server_state::instance()) + , wsrep::high_priority_context(thd->wsrep_cs()) + , m_thd(thd) + , m_rli() +{ + LEX_CSTRING db_str= { NULL, 0 }; + m_shadow.option_bits = thd->variables.option_bits; + m_shadow.server_status= thd->server_status; + m_shadow.vio = thd->net.vio; + m_shadow.tx_isolation = thd->variables.tx_isolation; + m_shadow.db = (char *)thd->db.str; + m_shadow.db_length = thd->db.length; + m_shadow.user_time = thd->user_time; + m_shadow.row_count_func= thd->get_row_count_func(); + m_shadow.wsrep_applier= thd->wsrep_applier; + + /* Disable general logging on applier threads */ + thd->variables.option_bits |= OPTION_LOG_OFF; + /* Enable binlogging if opt_log_slave_updates is set */ + if (opt_log_slave_updates) + thd->variables.option_bits|= OPTION_BIN_LOG; + else + thd->variables.option_bits&= ~(OPTION_BIN_LOG); + + thd->net.vio= 0; + thd->reset_db(&db_str); + thd->clear_error(); + thd->variables.tx_isolation= ISO_READ_COMMITTED; + thd->tx_isolation = ISO_READ_COMMITTED; + + /* From trans_begin() */ + thd->variables.option_bits|= OPTION_BEGIN; + thd->server_status|= SERVER_STATUS_IN_TRANS; + + /* Make THD wsrep_applier so that it cannot be killed */ + thd->wsrep_applier= true; + + if (!thd->wsrep_rgi) thd->wsrep_rgi= wsrep_relay_group_init(thd, "wsrep_relay"); + + m_rgi= thd->wsrep_rgi; + m_rgi->thd= thd; + m_rli= m_rgi->rli; + thd_proc_info(thd, "wsrep applier idle"); +} + +Wsrep_high_priority_service::~Wsrep_high_priority_service() +{ + THD* thd= m_thd; + thd->variables.option_bits = m_shadow.option_bits; + thd->server_status = m_shadow.server_status; + thd->net.vio = m_shadow.vio; + thd->variables.tx_isolation= m_shadow.tx_isolation; + LEX_CSTRING db_str= { m_shadow.db, m_shadow.db_length }; + thd->reset_db(&db_str); + thd->user_time = m_shadow.user_time; + + if (thd->wsrep_rgi && thd->wsrep_rgi->rli) + delete thd->wsrep_rgi->rli->mi; + if (thd->wsrep_rgi) + delete thd->wsrep_rgi->rli; + delete thd->wsrep_rgi; + thd->wsrep_rgi= NULL; + + thd->set_row_count_func(m_shadow.row_count_func); + thd->wsrep_applier = m_shadow.wsrep_applier; +} + +int Wsrep_high_priority_service::start_transaction( + const wsrep::ws_handle& ws_handle, const wsrep::ws_meta& ws_meta) +{ + DBUG_ENTER(" Wsrep_high_priority_service::start_transaction"); + DBUG_RETURN(m_thd->wsrep_cs().start_transaction(ws_handle, ws_meta)); +} + +const wsrep::transaction& Wsrep_high_priority_service::transaction() const +{ + DBUG_ENTER(" Wsrep_high_priority_service::transaction"); + DBUG_RETURN(m_thd->wsrep_trx()); +} + +void Wsrep_high_priority_service::adopt_transaction(const wsrep::transaction& transaction) +{ + DBUG_ENTER(" Wsrep_high_priority_service::adopt_transaction"); + m_thd->wsrep_cs().adopt_transaction(transaction); + DBUG_VOID_RETURN; +} + + +int Wsrep_high_priority_service::append_fragment_and_commit( + const wsrep::ws_handle& ws_handle, + const wsrep::ws_meta& ws_meta, + const wsrep::const_buffer& data) +{ + DBUG_ENTER("Wsrep_high_priority_service::append_fragment_and_commit"); + int ret= start_transaction(ws_handle, ws_meta); + /* + Start transaction explicitly to avoid early commit via + trans_commit_stmt() in append_fragment() + */ + ret= ret || trans_begin(m_thd); + ret= ret || wsrep_schema->append_fragment(m_thd, + ws_meta.server_id(), + ws_meta.transaction_id(), + ws_meta.seqno(), + ws_meta.flags(), + data); + + /* + Note: The commit code below seems to be identical to + Wsrep_storage_service::commit(). Consider implementing + common utility function to deal with commit. + */ + const bool do_binlog_commit= (opt_log_slave_updates && + wsrep_gtid_mode && + m_thd->variables.gtid_seq_no); + /* + Write skip event into binlog if gtid_mode is on. This is to + maintain gtid continuity. + */ + if (do_binlog_commit) + { + ret= wsrep_write_skip_event(m_thd); + } + + if (!ret) + { + ret= m_thd->wsrep_cs().prepare_for_ordering(ws_handle, + ws_meta, true); + } + + if (!ret) + { + DBUG_ASSERT(wsrep_thd_trx_seqno(m_thd) > 0); + if (!do_binlog_commit) + { + ret= wsrep_before_commit(m_thd, true); + } + ret= ret || trans_commit(m_thd); + if (!do_binlog_commit) + { + if (opt_log_slave_updates) + { + ret= ret || wsrep_ordered_commit(m_thd, true, wsrep_apply_error()); + } + ret= ret || wsrep_after_commit(m_thd, true); + } + } + m_thd->wsrep_cs().after_applying(); + m_thd->mdl_context.release_transactional_locks(); + + thd_proc_info(m_thd, "wsrep applier committed"); + + DBUG_RETURN(ret); +} + +int Wsrep_high_priority_service::remove_fragments(const wsrep::ws_meta& ws_meta) +{ + DBUG_ENTER("Wsrep_high_priority_service::remove_fragments"); + int ret= wsrep_schema->remove_fragments(m_thd, + ws_meta.server_id(), + ws_meta.transaction_id(), + m_thd->wsrep_sr().fragments()); + DBUG_RETURN(ret); +} + +int Wsrep_high_priority_service::commit(const wsrep::ws_handle& ws_handle, + const wsrep::ws_meta& ws_meta) +{ + DBUG_ENTER("Wsrep_high_priority_service::commit"); + THD* thd= m_thd; + DBUG_ASSERT(thd->wsrep_trx().active()); + thd->wsrep_cs().prepare_for_ordering(ws_handle, ws_meta, true); + thd_proc_info(thd, "committing"); + + int ret= 0; + const bool is_ordered= !ws_meta.seqno().is_undefined(); + /* If opt_log_slave_updates is not on, applier does not write + anything to binlog cache and neither wsrep_before_commit() + nor wsrep_after_commit() we be reached from binlog code + path for applier. Therefore run wsrep_before_commit() + and wsrep_after_commit() here. wsrep_ordered_commit() + will be called from wsrep_ordered_commit_if_no_binlog(). */ + if (!opt_log_slave_updates && !opt_bin_log && is_ordered) + { + if (m_thd->transaction.all.no_2pc == false) + { + ret= wsrep_before_prepare(thd, true); + ret= ret || wsrep_after_prepare(thd, true); + } + ret= ret || wsrep_before_commit(thd, true); + } + ret= ret || trans_commit(thd); + + if (ret == 0) + { + m_rgi->cleanup_context(thd, 0); + } + + if (ret == 0 && !opt_log_slave_updates && !opt_bin_log && is_ordered) + { + ret= wsrep_after_commit(thd, true); + } + + m_thd->mdl_context.release_transactional_locks(); + + thd_proc_info(thd, "wsrep applier committed"); + + if (!is_ordered) + { + /* Wsrep commit was not ordered so it does not go through commit time + hooks and remains active. Roll it back to make cleanup happen + in after_applying() call. */ + m_thd->wsrep_cs().before_rollback(); + m_thd->wsrep_cs().after_rollback(); + } + + must_exit_= check_exit_status(); + DBUG_RETURN(ret); +} + +int Wsrep_high_priority_service::rollback(const wsrep::ws_handle& ws_handle, + const wsrep::ws_meta& ws_meta) +{ + DBUG_ENTER("Wsrep_high_priority_service::rollback"); + m_thd->wsrep_cs().prepare_for_ordering(ws_handle, ws_meta, false); + int ret= (trans_rollback_stmt(m_thd) || trans_rollback(m_thd)); + m_thd->mdl_context.release_transactional_locks(); + m_thd->mdl_context.release_explicit_locks(); + DBUG_RETURN(ret); +} + +int Wsrep_high_priority_service::apply_toi(const wsrep::ws_meta& ws_meta, + const wsrep::const_buffer& data) +{ + DBUG_ENTER("Wsrep_high_priority_service::apply_toi"); + THD* thd= m_thd; + Wsrep_non_trans_mode non_trans_mode(thd, ws_meta); + + wsrep::client_state& client_state(thd->wsrep_cs()); + DBUG_ASSERT(client_state.in_toi()); + + thd_proc_info(thd, "wsrep applier toi"); + + WSREP_DEBUG("Wsrep_high_priority_service::apply_toi: %lld", + client_state.toi_meta().seqno().get()); + + int ret= wsrep_apply_events(thd, m_rli, data.data(), data.size()); + if (ret != 0 || thd->wsrep_has_ignored_error) + { + wsrep_dump_rbr_buf_with_header(thd, data.data(), data.size()); + thd->wsrep_has_ignored_error= false; + /* todo: error voting */ + } + trans_commit(thd); + + thd->close_temporary_tables(); + wsrep_set_SE_checkpoint(client_state.toi_meta().gtid()); + + must_exit_= check_exit_status(); + + DBUG_RETURN(ret); +} + +void Wsrep_high_priority_service::store_globals() +{ + DBUG_ENTER("Wsrep_high_priority_service::store_globals"); + /* In addition to calling THD::store_globals(), call + wsrep::client_state::store_globals() to gain ownership of + the client state */ + m_thd->store_globals(); + m_thd->wsrep_cs().store_globals(); + DBUG_VOID_RETURN; +} + +void Wsrep_high_priority_service::reset_globals() +{ + DBUG_ENTER("Wsrep_high_priority_service::reset_globals"); + m_thd->reset_globals(); + DBUG_VOID_RETURN; +} + +void Wsrep_high_priority_service::switch_execution_context(wsrep::high_priority_service& orig_high_priority_service) +{ + DBUG_ENTER("Wsrep_high_priority_service::switch_execution_context"); + Wsrep_high_priority_service& + orig_hps= static_cast<Wsrep_high_priority_service&>(orig_high_priority_service); + m_thd->thread_stack= orig_hps.m_thd->thread_stack; + DBUG_VOID_RETURN; +} + +int Wsrep_high_priority_service::log_dummy_write_set(const wsrep::ws_handle& ws_handle, + const wsrep::ws_meta& ws_meta) +{ + DBUG_ENTER("Wsrep_high_priority_service::log_dummy_write_set"); + int ret= 0; + DBUG_PRINT("info", + ("Wsrep_high_priority_service::log_dummy_write_set: seqno=%lld", + ws_meta.seqno().get())); + m_thd->wsrep_cs().start_transaction(ws_handle, ws_meta); + WSREP_DEBUG("Log dummy write set %lld", ws_meta.seqno().get()); + if (!(opt_log_slave_updates && wsrep_gtid_mode && m_thd->variables.gtid_seq_no)) + { + m_thd->wsrep_cs().before_rollback(); + m_thd->wsrep_cs().after_rollback(); + } + m_thd->wsrep_cs().after_applying(); + DBUG_RETURN(ret); +} + +void Wsrep_high_priority_service::debug_crash(const char* crash_point) +{ + DBUG_ASSERT(m_thd == current_thd); + DBUG_EXECUTE_IF(crash_point, DBUG_SUICIDE();); +} + +/**************************************************************************** + Applier service +*****************************************************************************/ + +Wsrep_applier_service::Wsrep_applier_service(THD* thd) + : Wsrep_high_priority_service(thd) +{ + thd->wsrep_applier_service= this; + thd->wsrep_cs().open(wsrep::client_id(thd->thread_id)); + thd->wsrep_cs().before_command(); + thd->wsrep_cs().debug_log_level(wsrep_debug); + +} + +Wsrep_applier_service::~Wsrep_applier_service() +{ + m_thd->wsrep_cs().after_command_before_result(); + m_thd->wsrep_cs().after_command_after_result(); + m_thd->wsrep_cs().close(); + m_thd->wsrep_cs().cleanup(); +} + +int Wsrep_applier_service::apply_write_set(const wsrep::ws_meta& ws_meta, + const wsrep::const_buffer& data) +{ + DBUG_ENTER("Wsrep_applier_service::apply_write_set"); + THD* thd= m_thd; + + thd->variables.option_bits |= OPTION_BEGIN; + thd->variables.option_bits |= OPTION_NOT_AUTOCOMMIT; + DBUG_ASSERT(thd->wsrep_trx().active()); + DBUG_ASSERT(thd->wsrep_trx().state() == wsrep::transaction::s_executing); + + thd_proc_info(thd, "applying write set"); + /* 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[]= + "now " + "SIGNAL sync.wsrep_apply_cb_reached " + "WAIT_FOR signal.wsrep_apply_cb"; + DBUG_ASSERT(!debug_sync_set_action(thd, + STRING_WITH_LEN(act))); + };); + + wsrep_setup_uk_and_fk_checks(thd); + + int ret= wsrep_apply_events(thd, m_rli, data.data(), data.size()); + + if (ret || thd->wsrep_has_ignored_error) + { + wsrep_dump_rbr_buf_with_header(thd, data.data(), data.size()); + } + + thd->close_temporary_tables(); + if (!ret && !(ws_meta.flags() & wsrep::provider::flag::commit)) + { + thd->wsrep_cs().fragment_applied(ws_meta.seqno()); + } + thd_proc_info(thd, "wsrep applied write set"); + DBUG_RETURN(ret); +} + +void Wsrep_applier_service::after_apply() +{ + DBUG_ENTER("Wsrep_applier_service::after_apply"); + wsrep_after_apply(m_thd); + DBUG_VOID_RETURN; +} + +bool Wsrep_applier_service::check_exit_status() const +{ + bool ret= false; + mysql_mutex_lock(&LOCK_wsrep_slave_threads); + if (wsrep_slave_count_change < 0) + { + ++wsrep_slave_count_change; + ret= true; + } + mysql_mutex_unlock(&LOCK_wsrep_slave_threads); + return ret; +} + +/**************************************************************************** + Replayer service +*****************************************************************************/ + +Wsrep_replayer_service::Wsrep_replayer_service(THD* thd) + : Wsrep_high_priority_service(thd) + , m_da_shadow() + , m_replay_status() +{ + /* Response must not have been sent to client */ + DBUG_ASSERT(!thd->get_stmt_da()->is_sent()); + /* PS reprepare observer should have been removed already + open_table() will fail if we have dangling observer here */ + DBUG_ASSERT(!thd->m_reprepare_observer); + /* Replaying should happen always from after_statement() hook + after rollback, which should guarantee that there are no + transactional locks */ + DBUG_ASSERT(!thd->mdl_context.has_transactional_locks()); + + /* Make a shadow copy of diagnostics area and reset */ + m_da_shadow.status= thd->get_stmt_da()->status(); + if (m_da_shadow.status == Diagnostics_area::DA_OK) + { + m_da_shadow.affected_rows= thd->get_stmt_da()->affected_rows(); + m_da_shadow.last_insert_id= thd->get_stmt_da()->last_insert_id(); + strmake(m_da_shadow.message, thd->get_stmt_da()->message(), + sizeof(m_da_shadow.message) - 1); + } + thd->get_stmt_da()->reset_diagnostics_area(); + + /* Release explicit locks */ + if (thd->locked_tables_mode && thd->lock) + { + WSREP_WARN("releasing table lock for replaying (%llu)", + thd->thread_id); + thd->locked_tables_list.unlock_locked_tables(thd); + thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); + } + + /* + Replaying will call MYSQL_START_STATEMENT when handling + BEGIN Query_log_event so end statement must be called before + replaying. + */ + MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da()); + thd->m_statement_psi= NULL; + thd->m_digest= NULL; + thd_proc_info(thd, "wsrep replaying trx"); +} + +Wsrep_replayer_service::~Wsrep_replayer_service() +{ + THD* thd= m_thd; + DBUG_ASSERT(!thd->get_stmt_da()->is_sent()); + DBUG_ASSERT(!thd->get_stmt_da()->is_set()); + if (m_replay_status == wsrep::provider::success) + { + DBUG_ASSERT(thd->wsrep_cs().current_error() == wsrep::e_success); + thd->killed= NOT_KILLED; + if (m_da_shadow.status == Diagnostics_area::DA_OK) + { + my_ok(thd, + m_da_shadow.affected_rows, + m_da_shadow.last_insert_id, + m_da_shadow.message); + } + else + { + my_ok(thd); + } + } + else if (m_replay_status == wsrep::provider::error_certification_failed) + { + DBUG_ASSERT(thd->wsrep_cs().current_error() == wsrep::e_deadlock_error); + } + else + { + DBUG_ASSERT(0); + WSREP_ERROR("trx_replay failed for: %d, schema: %s, query: %s", + m_replay_status, + thd->db.str, WSREP_QUERY(thd)); + unireg_abort(1); + } +} + +int Wsrep_replayer_service::apply_write_set(const wsrep::ws_meta& ws_meta, + const wsrep::const_buffer& data) +{ + DBUG_ENTER("Wsrep_replayer_service::apply_write_set"); + THD* thd= m_thd; + + DBUG_ASSERT(thd->wsrep_trx().active()); + DBUG_ASSERT(thd->wsrep_trx().state() == wsrep::transaction::s_replaying); + + wsrep_setup_uk_and_fk_checks(thd); + + int ret= 0; + if (!wsrep::starts_transaction(ws_meta.flags())) + { + DBUG_ASSERT(thd->wsrep_trx().is_streaming()); + ret= wsrep_schema->replay_transaction(thd, + m_rli, + ws_meta, + thd->wsrep_sr().fragments()); + } + + ret= ret || wsrep_apply_events(thd, m_rli, data.data(), data.size()); + + if (ret || thd->wsrep_has_ignored_error) + { + wsrep_dump_rbr_buf_with_header(thd, data.data(), data.size()); + } + + thd->close_temporary_tables(); + if (!ret && !(ws_meta.flags() & wsrep::provider::flag::commit)) + { + thd->wsrep_cs().fragment_applied(ws_meta.seqno()); + } + + thd_proc_info(thd, "wsrep replayed write set"); + DBUG_RETURN(ret); +} diff --git a/sql/wsrep_high_priority_service.h b/sql/wsrep_high_priority_service.h new file mode 100644 index 00000000000..4012ca60a3e --- /dev/null +++ b/sql/wsrep_high_priority_service.h @@ -0,0 +1,118 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef WSREP_HIGH_PRIORITY_SERVICE_H +#define WSREP_HIGH_PRIORITY_SERVICE_H + +#include "wsrep/high_priority_service.hpp" +#include "wsrep/client_state.hpp" +#include "my_global.h" +#include "sql_error.h" /* Diagnostics area */ +#include "sql_class.h" /* rpl_group_info */ + +class THD; +class Relay_log_info; +class Wsrep_server_service; + +class Wsrep_high_priority_service : + public wsrep::high_priority_service, + public wsrep::high_priority_context +{ +public: + Wsrep_high_priority_service(THD*); + ~Wsrep_high_priority_service(); + int start_transaction(const wsrep::ws_handle&, + const wsrep::ws_meta&); + const wsrep::transaction& transaction() const; + void adopt_transaction(const wsrep::transaction&); + int apply_write_set(const wsrep::ws_meta&, const wsrep::const_buffer&) = 0; + int append_fragment_and_commit(const wsrep::ws_handle&, + const wsrep::ws_meta&, + const wsrep::const_buffer&); + int remove_fragments(const wsrep::ws_meta&); + int commit(const wsrep::ws_handle&, const wsrep::ws_meta&); + int rollback(const wsrep::ws_handle&, const wsrep::ws_meta&); + int apply_toi(const wsrep::ws_meta&, const wsrep::const_buffer&); + void store_globals(); + void reset_globals(); + void switch_execution_context(wsrep::high_priority_service&); + int log_dummy_write_set(const wsrep::ws_handle&, + const wsrep::ws_meta&); + + virtual bool check_exit_status() const = 0; + void debug_crash(const char*); +protected: + friend Wsrep_server_service; + THD* m_thd; + Relay_log_info* m_rli; + rpl_group_info* m_rgi; + struct shadow + { + ulonglong option_bits; + uint server_status; + struct st_vio* vio; + ulong tx_isolation; + char* db; + size_t db_length; + //struct timeval user_time; + my_hrtime_t user_time; + longlong row_count_func; + bool wsrep_applier; +} m_shadow; +}; + +class Wsrep_applier_service : public Wsrep_high_priority_service +{ +public: + Wsrep_applier_service(THD*); + ~Wsrep_applier_service(); + int apply_write_set(const wsrep::ws_meta&, const wsrep::const_buffer&); + void after_apply(); + bool is_replaying() const { return false; } + bool check_exit_status() const; +}; + +class Wsrep_replayer_service : public Wsrep_high_priority_service +{ +public: + Wsrep_replayer_service(THD*); + ~Wsrep_replayer_service(); + int apply_write_set(const wsrep::ws_meta&, const wsrep::const_buffer&); + void after_apply() { } + bool is_replaying() const { return true; } + void replay_status(enum wsrep::provider::status status) + { m_replay_status = status; } + enum wsrep::provider::status replay_status() const + { return m_replay_status; } + /* Replayer should never be forced to exit */ + bool check_exit_status() const { return false; } +private: + struct da_shadow + { + enum Diagnostics_area::enum_diagnostics_status status; + ulonglong affected_rows; + ulonglong last_insert_id; + char message[MYSQL_ERRMSG_SIZE]; + da_shadow() + : status() + , affected_rows() + , last_insert_id() + , message() + { } + } m_da_shadow; + enum wsrep::provider::status m_replay_status; +}; + +#endif /* WSREP_HIGH_PRIORITY_SERVICE_H */ diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc deleted file mode 100644 index 8110faf7d11..00000000000 --- a/sql/wsrep_hton.cc +++ /dev/null @@ -1,658 +0,0 @@ -/* Copyright 2008-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 - 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 02111-1301 USA */ - -#include "mariadb.h" -#include <mysqld.h> -#include "sql_base.h" -#include "rpl_filter.h" -#include <sql_class.h> -#include "wsrep_mysqld.h" -#include "wsrep_binlog.h" -#include "wsrep_xid.h" -#include <cstdio> -#include <cstdlib> -#include "debug_sync.h" - -extern handlerton *binlog_hton; -extern int binlog_close_connection(handlerton *hton, THD *thd); -extern ulonglong thd_to_trx_id(THD *thd); - -extern "C" int thd_binlog_format(const MYSQL_THD thd); -// todo: share interface with ha_innodb.c - -/* - Cleanup after local transaction commit/rollback, replay or TOI. -*/ -void wsrep_cleanup_transaction(THD *thd) -{ - if (!WSREP(thd)) return; - - if (wsrep_emulate_bin_log) thd_binlog_trx_reset(thd); - thd->wsrep_ws_handle.trx_id= WSREP_UNDEFINED_TRX_ID; - thd->wsrep_trx_meta.gtid= WSREP_GTID_UNDEFINED; - thd->wsrep_trx_meta.depends_on= WSREP_SEQNO_UNDEFINED; - thd->wsrep_exec_mode= LOCAL_STATE; - thd->wsrep_affected_rows= 0; - thd->wsrep_skip_wsrep_GTID= false; - return; -} - -/* - wsrep hton -*/ -handlerton *wsrep_hton; - - -/* - Registers wsrep hton at commit time if transaction has registered htons - for supported engine types. - - Hton should not be registered for TOTAL_ORDER operations. - - Registration is needed for both LOCAL_MODE and REPL_RECV transactions to run - commit in 2pc so that wsrep position gets properly recorded in storage - engines. - - Note that all hton calls should immediately return for threads that are - in REPL_RECV mode as their states are controlled by wsrep appliers or - replaying code. Only threads in LOCAL_MODE should run wsrep callbacks - from hton methods. -*/ -void wsrep_register_hton(THD* thd, bool all) -{ - if (WSREP(thd) && thd->wsrep_exec_mode != TOTAL_ORDER && - !thd->wsrep_apply_toi) - { - if (thd->wsrep_exec_mode == LOCAL_STATE && - (thd_sql_command(thd) == SQLCOM_OPTIMIZE || - thd_sql_command(thd) == SQLCOM_ANALYZE || - thd_sql_command(thd) == SQLCOM_REPAIR) && - thd->lex->no_write_to_binlog == 1) - { - WSREP_DEBUG("Skipping wsrep_register_hton for LOCAL sql admin command : %s", - thd->query()); - return; - } - - THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt; - for (Ha_trx_info *i= trans->ha_list; i; i = i->next()) - { - if ((i->ht()->db_type == DB_TYPE_INNODB) || - (i->ht()->db_type == DB_TYPE_TOKUDB)) - { - trans_register_ha(thd, all, wsrep_hton); - - /* follow innodb read/write settting - * but, as an exception: CTAS with empty result set will not be - * replicated unless we declare wsrep hton as read/write here - */ - if (i->is_trx_read_write() || - ((thd->lex->sql_command == SQLCOM_CREATE_TABLE || - thd->lex->sql_command == SQLCOM_CREATE_SEQUENCE) && - thd->wsrep_exec_mode == LOCAL_STATE)) - { - thd->ha_data[wsrep_hton->slot].ha_info[all].set_trx_read_write(); - } - break; - } - } - } -} - -/* - Calls wsrep->post_commit() for locally executed transactions that have - got seqno from provider (must commit) and don't require replaying. - */ -void wsrep_post_commit(THD* thd, bool all) -{ - if (!WSREP(thd)) return; - - switch (thd->wsrep_exec_mode) - { - case LOCAL_COMMIT: - { - DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED); - if (wsrep && wsrep->post_commit(wsrep, &thd->wsrep_ws_handle)) - { - DBUG_PRINT("wsrep", ("set committed fail")); - WSREP_WARN("set committed fail: %llu %d", - (long long)thd->real_id, thd->get_stmt_da()->status()); - } - wsrep_cleanup_transaction(thd); - break; - } - case LOCAL_STATE: - { - /* non-InnoDB statements may have populated events in stmt cache - => cleanup - */ - WSREP_DEBUG("cleanup transaction for LOCAL_STATE"); - /* - Run post-rollback hook to clean up in the case if - some keys were populated for the transaction in provider - but during commit time there was no write set to replicate. - This may happen when client sets the SAVEPOINT and immediately - rolls back to savepoint after first operation. - */ - if (all && thd->wsrep_conflict_state != MUST_REPLAY && - wsrep && wsrep->post_rollback(wsrep, &thd->wsrep_ws_handle)) - { - WSREP_WARN("post_rollback fail: %llu %d", - (long long)thd->thread_id, thd->get_stmt_da()->status()); - } - wsrep_cleanup_transaction(thd); - break; - } - default: break; - } -} - -/* - wsrep exploits binlog's caches even if binlogging itself is not - activated. In such case connection close needs calling - actual binlog's method. - Todo: split binlog hton from its caches to use ones by wsrep - without referring to binlog's stuff. -*/ -static int -wsrep_close_connection(handlerton* hton, THD* thd) -{ - DBUG_ENTER("wsrep_close_connection"); - - if (thd->wsrep_exec_mode == REPL_RECV) - { - DBUG_RETURN(0); - } - - if (wsrep_emulate_bin_log && thd_get_ha_data(thd, binlog_hton) != NULL) - binlog_hton->close_connection (binlog_hton, thd); - DBUG_RETURN(0); -} - -/* - prepare/wsrep_run_wsrep_commit can fail in two ways - - certification test or an equivalent. As a result, - the current transaction just rolls back - Error codes: - WSREP_TRX_CERT_FAIL, WSREP_TRX_SIZE_EXCEEDED, WSREP_TRX_ERROR - - a post-certification failure makes this server unable to - commit its own WS and therefore the server must abort -*/ -static int wsrep_prepare(handlerton *hton, THD *thd, bool all) -{ - DBUG_ENTER("wsrep_prepare"); - - if (thd->wsrep_exec_mode == REPL_RECV) - { - DBUG_RETURN(0); - } - - DBUG_ASSERT(thd->ha_data[wsrep_hton->slot].ha_info[all].is_trx_read_write()); - DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_STATE); - DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno == WSREP_SEQNO_UNDEFINED); - - if ((all || - !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && - (thd->variables.wsrep_on && !wsrep_trans_cache_is_empty(thd))) - { - int res= wsrep_run_wsrep_commit(thd, all); - if (res != 0) - { - if (res == WSREP_TRX_SIZE_EXCEEDED) - res= EMSGSIZE; - else - res= EDEADLK; // for a better error message - } - DBUG_RETURN (res); - } - DBUG_RETURN(0); -} - -static int wsrep_savepoint_set(handlerton *hton, THD *thd, void *sv) -{ - DBUG_ENTER("wsrep_savepoint_set"); - - if (thd->wsrep_exec_mode == REPL_RECV) - { - DBUG_RETURN(0); - } - - if (!wsrep_emulate_bin_log) DBUG_RETURN(0); - int rcode = wsrep_binlog_savepoint_set(thd, sv); - DBUG_RETURN(rcode); -} - -static int wsrep_savepoint_rollback(handlerton *hton, THD *thd, void *sv) -{ - DBUG_ENTER("wsrep_savepoint_rollback"); - - if (thd->wsrep_exec_mode == REPL_RECV) - { - DBUG_RETURN(0); - } - - if (!wsrep_emulate_bin_log) DBUG_RETURN(0); - int rcode = wsrep_binlog_savepoint_rollback(thd, sv); - DBUG_RETURN(rcode); -} - -static int wsrep_rollback(handlerton *hton, THD *thd, bool all) -{ - DBUG_ENTER("wsrep_rollback"); - - if (thd->wsrep_exec_mode == REPL_RECV) - { - DBUG_RETURN(0); - } - - mysql_mutex_lock(&thd->LOCK_thd_data); - switch (thd->wsrep_exec_mode) - { - case TOTAL_ORDER: - case REPL_RECV: - mysql_mutex_unlock(&thd->LOCK_thd_data); - WSREP_DEBUG("Avoiding wsrep rollback for failed DDL: %s", thd->query()); - DBUG_RETURN(0); - default: break; - } - - if ((all || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && - thd->variables.wsrep_on && thd->wsrep_conflict_state != MUST_REPLAY) - { - if (wsrep && wsrep->post_rollback(wsrep, &thd->wsrep_ws_handle)) - { - DBUG_PRINT("wsrep", ("setting rollback fail")); - WSREP_ERROR("settting rollback fail: thd: %llu, schema: %s, SQL: %s", - (long long)thd->real_id, thd->get_db(), thd->query()); - } - wsrep_cleanup_transaction(thd); - } - mysql_mutex_unlock(&thd->LOCK_thd_data); - DBUG_RETURN(0); -} - -int wsrep_commit(handlerton *hton, THD *thd, bool all) -{ - DBUG_ENTER("wsrep_commit"); - - if (thd->wsrep_exec_mode == REPL_RECV) - { - DBUG_RETURN(0); - } - - mysql_mutex_lock(&thd->LOCK_thd_data); - if ((all || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && - (thd->variables.wsrep_on && thd->wsrep_conflict_state != MUST_REPLAY)) - { - if (thd->wsrep_exec_mode == LOCAL_COMMIT) - { - DBUG_ASSERT(thd->ha_data[wsrep_hton->slot].ha_info[all].is_trx_read_write()); - /* - Call to wsrep->post_commit() (moved to wsrep_post_commit()) must - be done only after commit has done for all involved htons. - */ - DBUG_PRINT("wsrep", ("commit")); - } - else - { - /* - Transaction didn't go through wsrep->pre_commit() so just roll back - possible changes to clean state. - */ - if (WSREP_PROVIDER_EXISTS) { - if (wsrep && wsrep->post_rollback(wsrep, &thd->wsrep_ws_handle)) - { - DBUG_PRINT("wsrep", ("setting rollback fail")); - WSREP_ERROR("settting rollback fail: thd: %llu, schema: %s, SQL: %s", - (long long)thd->real_id, thd->get_db(), - thd->query()); - } - } - wsrep_cleanup_transaction(thd); - } - } - mysql_mutex_unlock(&thd->LOCK_thd_data); - DBUG_RETURN(0); -} - - -extern Rpl_filter* binlog_filter; -extern my_bool opt_log_slave_updates; - -enum wsrep_trx_status -wsrep_run_wsrep_commit(THD *thd, bool all) -{ - int rcode= -1; - size_t data_len= 0; - IO_CACHE *cache; - int replay_round= 0; - DBUG_ENTER("wsrep_run_wsrep_commit"); - - if (thd->get_stmt_da()->is_error()) { - WSREP_DEBUG("commit issue, error: %d %s", - thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message()); - } - - DEBUG_SYNC(thd, "wsrep_before_replication"); - - if (thd->slave_thread && !opt_log_slave_updates) DBUG_RETURN(WSREP_TRX_OK); - - if (thd->wsrep_exec_mode == REPL_RECV) { - - mysql_mutex_lock(&thd->LOCK_thd_data); - if (thd->wsrep_conflict_state == MUST_ABORT) { - if (wsrep_debug) - WSREP_INFO("WSREP: must abort for BF"); - DBUG_PRINT("wsrep", ("BF apply commit fail")); - thd->wsrep_conflict_state = NO_CONFLICT; - mysql_mutex_unlock(&thd->LOCK_thd_data); - // - // TODO: test all calls of the rollback. - // rollback must happen automagically innobase_rollback(hton, thd, 1); - // - DBUG_RETURN(WSREP_TRX_ERROR); - } - mysql_mutex_unlock(&thd->LOCK_thd_data); - } - - if (thd->wsrep_exec_mode != LOCAL_STATE) DBUG_RETURN(WSREP_TRX_OK); - - if (thd->wsrep_consistency_check == CONSISTENCY_CHECK_RUNNING) { - WSREP_DEBUG("commit for consistency check: %s", thd->query()); - DBUG_RETURN(WSREP_TRX_OK); - } - - DBUG_PRINT("wsrep", ("replicating commit")); - - mysql_mutex_lock(&thd->LOCK_thd_data); - if (thd->wsrep_conflict_state == MUST_ABORT) { - DBUG_PRINT("wsrep", ("replicate commit fail")); - thd->wsrep_conflict_state = ABORTED; - mysql_mutex_unlock(&thd->LOCK_thd_data); - if (wsrep_debug) { - WSREP_INFO("innobase_commit, abort %s", - (thd->query()) ? thd->query() : "void"); - } - DBUG_RETURN(WSREP_TRX_CERT_FAIL); - } - - mysql_mutex_lock(&LOCK_wsrep_replaying); - - DBUG_PRINT("info", ("wsrep_replaying: %d wsrep_conflict_state: %d killed: %d shutdown_in_progress: %d", - (int) wsrep_replaying, (int) thd->wsrep_conflict_state, - (int) thd->killed, - (int) shutdown_in_progress)); - - 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_thd_data); - - 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 = {0, 1000000}; - 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, (longlong) thd->thread_id, - thd->wsrep_conflict_state, 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_thd_data); - mysql_mutex_lock(&LOCK_wsrep_replaying); - } - mysql_mutex_unlock(&LOCK_wsrep_replaying); - - if (thd->wsrep_conflict_state == MUST_ABORT) { - DBUG_PRINT("wsrep", ("replicate commit fail")); - thd->wsrep_conflict_state = ABORTED; - mysql_mutex_unlock(&thd->LOCK_thd_data); - WSREP_DEBUG("innobase_commit abort after replaying wait %s", - (thd->query()) ? thd->query() : "void"); - DBUG_RETURN(WSREP_TRX_CERT_FAIL); - } - - thd->wsrep_query_state = QUERY_COMMITTING; - mysql_mutex_unlock(&thd->LOCK_thd_data); - - cache = get_trans_log(thd); - rcode = 0; - if (cache) { - thd->binlog_flush_pending_rows_event(true); - rcode = wsrep_write_cache(wsrep, thd, cache, &data_len); - if (WSREP_OK != rcode) { - WSREP_ERROR("rbr write fail, data_len: %zu, %d", data_len, rcode); - DBUG_RETURN(WSREP_TRX_SIZE_EXCEEDED); - } - } - - DBUG_PRINT("info", ("rcode: %d wsrep_conflict_state: %d", - rcode, thd->wsrep_conflict_state)); - - 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)", - 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); - } - else - { - WSREP_DEBUG("empty rbr buffer, query: %s", thd->query()); - } - thd->wsrep_query_state= QUERY_EXEC; - DBUG_RETURN(WSREP_TRX_OK); - } - - if (WSREP_UNDEFINED_TRX_ID == thd->wsrep_ws_handle.trx_id) - { - WSREP_WARN("SQL statement was ineffective thd: %lld buf: %zu\n" - "schema: %s \n" - "QUERY: %s\n" - " => Skipping replication", - (longlong) thd->thread_id, data_len, - thd->get_db(), thd->query()); - rcode = WSREP_TRX_FAIL; - } - else if (!rcode) - { - if (WSREP_OK == rcode && wsrep) - rcode = wsrep->pre_commit(wsrep, - (wsrep_conn_id_t)thd->thread_id, - &thd->wsrep_ws_handle, - WSREP_FLAG_COMMIT | - ((thd->wsrep_PA_safe) ? - 0ULL : WSREP_FLAG_PA_UNSAFE), - &thd->wsrep_trx_meta); - - DBUG_PRINT("info", ("rcode after pre_commit: %d", rcode)); - - if (rcode == WSREP_TRX_MISSING) { - WSREP_WARN("Transaction missing in provider, thd: %lld schema: %s SQL: %s", - (longlong) thd->thread_id, - thd->get_db(), thd->query()); - rcode = WSREP_TRX_FAIL; - } else if (rcode == WSREP_BF_ABORT) { - WSREP_DEBUG("thd: %lld seqno: %lld BF aborted by provider, will replay", - (longlong) thd->thread_id, - (longlong) thd->wsrep_trx_meta.gtid.seqno); - mysql_mutex_lock(&thd->LOCK_thd_data); - thd->wsrep_conflict_state = MUST_REPLAY; - DBUG_ASSERT(wsrep_thd_trx_seqno(thd) > 0); - mysql_mutex_unlock(&thd->LOCK_thd_data); - mysql_mutex_lock(&LOCK_wsrep_replaying); - wsrep_replaying++; - WSREP_DEBUG("replaying increased: %d, thd: %lld", - wsrep_replaying, (longlong) thd->thread_id); - mysql_mutex_unlock(&LOCK_wsrep_replaying); - } - } else { - WSREP_ERROR("I/O error reading from thd's binlog iocache: " - "errno=%d, io cache code=%d", my_errno, cache->error); - DBUG_ASSERT(0); // failure like this can not normally happen - DBUG_RETURN(WSREP_TRX_ERROR); - } - - mysql_mutex_lock(&thd->LOCK_thd_data); - - DEBUG_SYNC(thd, "wsrep_after_replication"); - - DBUG_PRINT("info", ("rcode: %d wsrep_conflict_state: %d", - rcode, thd->wsrep_conflict_state)); - - switch(rcode) { - case 0: - /* - About MUST_ABORT: We assume that even if thd conflict state was set - to MUST_ABORT, underlying transaction was not rolled back or marked - as deadlock victim in QUERY_COMMITTING state. Conflict state is - set to NO_CONFLICT and commit proceeds as usual. - */ - if (thd->wsrep_conflict_state == MUST_ABORT) - thd->wsrep_conflict_state= NO_CONFLICT; - - if (thd->wsrep_conflict_state != NO_CONFLICT) - { - WSREP_WARN("thd: %llu seqno: %lld conflict state %d after post commit", - (longlong) thd->thread_id, - (longlong) thd->wsrep_trx_meta.gtid.seqno, - thd->wsrep_conflict_state); - } - thd->wsrep_exec_mode= LOCAL_COMMIT; - DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED); - /* Override XID iff it was generated by mysql */ - if (thd->transaction.xid_state.xid.get_my_xid()) - { - wsrep_xid_init(&thd->transaction.xid_state.xid, - thd->wsrep_trx_meta.gtid.uuid, - thd->wsrep_trx_meta.gtid.seqno); - } - DBUG_PRINT("wsrep", ("replicating commit success")); - break; - case WSREP_BF_ABORT: - DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED); - /* fall through */ - case WSREP_TRX_FAIL: - WSREP_DEBUG("commit failed for reason: %d", rcode); - DBUG_PRINT("wsrep", ("replicating commit fail")); - - thd->wsrep_query_state= QUERY_EXEC; - - if (thd->wsrep_conflict_state == MUST_ABORT) { - thd->wsrep_conflict_state= ABORTED; - } - else - { - WSREP_DEBUG("conflict state: %d", thd->wsrep_conflict_state); - if (thd->wsrep_conflict_state == NO_CONFLICT) - { - thd->wsrep_conflict_state = CERT_FAILURE; - WSREP_LOG_CONFLICT(NULL, thd, FALSE); - } - } - mysql_mutex_unlock(&thd->LOCK_thd_data); - - DBUG_RETURN(WSREP_TRX_CERT_FAIL); - - case WSREP_SIZE_EXCEEDED: - WSREP_ERROR("transaction size exceeded"); - mysql_mutex_unlock(&thd->LOCK_thd_data); - DBUG_RETURN(WSREP_TRX_SIZE_EXCEEDED); - case WSREP_CONN_FAIL: - WSREP_ERROR("connection failure"); - mysql_mutex_unlock(&thd->LOCK_thd_data); - DBUG_RETURN(WSREP_TRX_ERROR); - default: - WSREP_ERROR("unknown connection failure"); - mysql_mutex_unlock(&thd->LOCK_thd_data); - DBUG_RETURN(WSREP_TRX_ERROR); - } - - thd->wsrep_query_state= QUERY_EXEC; - mysql_mutex_unlock(&thd->LOCK_thd_data); - - DBUG_RETURN(WSREP_TRX_OK); -} - - -static int wsrep_hton_init(void *p) -{ - wsrep_hton= (handlerton *)p; - //wsrep_hton->state=opt_bin_log ? SHOW_OPTION_YES : SHOW_OPTION_NO; - wsrep_hton->state= SHOW_OPTION_YES; - wsrep_hton->db_type=(legacy_db_type)0; - wsrep_hton->savepoint_offset= sizeof(my_off_t); - wsrep_hton->close_connection= wsrep_close_connection; - wsrep_hton->savepoint_set= wsrep_savepoint_set; - wsrep_hton->savepoint_rollback= wsrep_savepoint_rollback; - wsrep_hton->commit= wsrep_commit; - wsrep_hton->rollback= wsrep_rollback; - wsrep_hton->prepare= wsrep_prepare; - wsrep_hton->flags= HTON_NOT_USER_SELECTABLE | HTON_HIDDEN; // todo: fix flags - return 0; -} - - -struct st_mysql_storage_engine wsrep_storage_engine= -{ MYSQL_HANDLERTON_INTERFACE_VERSION }; - - -maria_declare_plugin(wsrep) -{ - MYSQL_STORAGE_ENGINE_PLUGIN, - &wsrep_storage_engine, - "wsrep", - "Codership Oy", - "A pseudo storage engine to represent transactions in multi-master " - "synchornous replication", - PLUGIN_LICENSE_GPL, - wsrep_hton_init, /* Plugin Init */ - NULL, /* Plugin Deinit */ - 0x0100 /* 1.0 */, - NULL, /* status variables */ - NULL, /* system variables */ - "1.0", /* string version */ - MariaDB_PLUGIN_MATURITY_STABLE /* maturity */ -} -maria_declare_plugin_end; diff --git a/sql/wsrep_mutex.h b/sql/wsrep_mutex.h new file mode 100644 index 00000000000..3454b44e0ec --- /dev/null +++ b/sql/wsrep_mutex.h @@ -0,0 +1,50 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef WSREP_MUTEX_H +#define WSREP_MUTEX_H + +/* wsrep-lib */ +#include "wsrep/mutex.hpp" + +/* implementation */ +#include "my_pthread.h" + +class Wsrep_mutex : public wsrep::mutex +{ +public: + Wsrep_mutex(mysql_mutex_t& mutex) + : m_mutex(mutex) + { } + + void lock() + { + mysql_mutex_lock(&m_mutex); + } + + void unlock() + { + mysql_mutex_unlock(&m_mutex); + } + + void* native() + { + return &m_mutex; + } +private: + mysql_mutex_t& m_mutex; +}; + +#endif /* WSREP_MUTEX_H */ diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 58b30a1e77f..73f201f12ca 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -14,7 +14,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ #include "sql_plugin.h" /* wsrep_plugins_pre_init() */ +#include "my_global.h" +#include "wsrep_server_state.h" + +#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,26 +38,32 @@ #include "wsrep_var.h" #include "wsrep_binlog.h" #include "wsrep_applier.h" +#include "wsrep_schema.h" #include "wsrep_xid.h" +#include "wsrep_trans_observer.h" +#include "mysql/service_wsrep.h" #include <cstdio> #include <cstdlib> +#include <string> #include "log_event.h" #include <slave.h> -wsrep_t *wsrep = NULL; -/* - wsrep_emulate_bin_log is a flag to tell that binlog has not been configured. - wsrep needs to get binlog events from transaction cache even when binlog is - not enabled, wsrep_emulate_bin_log opens needed code paths to make this - possible -*/ -my_bool wsrep_emulate_bin_log = FALSE; // activating parts of binlog interface +#include <sstream> + +/* wsrep-lib */ +Wsrep_server_state* Wsrep_server_state::m_instance; + +my_bool wsrep_emulate_bin_log = FALSE; // activating parts of binlog interface #ifdef GTID_SUPPORT /* Sidno in global_sid_map corresponding to group uuid */ rpl_sidno wsrep_sidno= -1; #endif /* GTID_SUPPORT */ my_bool wsrep_preordered_opt= FALSE; +/* Streaming Replication */ +const char *wsrep_fragment_units[]= { "bytes", "rows", "statements", NullS }; +const char *wsrep_SR_store_types[]= { "none", "table", NullS }; + /* * Begin configuration options */ @@ -82,7 +93,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_restart_slave; // Should mysql slave thread be @@ -107,7 +118,13 @@ 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_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 @@ -123,29 +140,33 @@ 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; int wsrep_replaying= 0; -ulong wsrep_running_threads = 0; // # of currently running wsrep threads +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_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_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_thd_queue; + PSI_file_key key_file_wsrep_gra_log; @@ -156,11 +177,12 @@ 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_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} }; static PSI_cond_info wsrep_conds[]= @@ -169,7 +191,7 @@ static PSI_cond_info wsrep_conds[]= { &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_thd, "THD::COND_wsrep_thd", 0}, { &key_COND_wsrep_replaying, "COND_wsrep_replaying", PSI_FLAG_GLOBAL} }; @@ -179,310 +201,219 @@ static PSI_file_info wsrep_files[]= }; #endif -my_bool wsrep_inited = 0; // initialized ? +my_bool wsrep_inited= 0; // initialized ? -static wsrep_uuid_t cluster_uuid = WSREP_UUID_UNDEFINED; +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] = -{ - "Primary", - "non-Primary", - "Disconnected" -}; static char provider_name[256]= { 0, }; static char provider_version[256]= { 0, }; static char provider_vendor[256]= { 0, }; /* - * wsrep status variables + * Wsrep status variables. LOCK_status must be locked When modifying + * these variables, */ -my_bool wsrep_connected = FALSE; -my_bool wsrep_ready = FALSE; // node can accept queries -const char* wsrep_cluster_state_uuid = cluster_uuid_str; -long long wsrep_cluster_conf_id = WSREP_SEQNO_UNDEFINED; -const char* wsrep_cluster_status = cluster_status_str[WSREP_VIEW_DISCONNECTED]; -long wsrep_cluster_size = 0; -long wsrep_local_index = -1; -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; +my_bool wsrep_connected = FALSE; +my_bool wsrep_ready = FALSE; +const char* wsrep_cluster_state_uuid= cluster_uuid_str; +long long wsrep_cluster_conf_id = WSREP_SEQNO_UNDEFINED; +const char* wsrep_cluster_status = "Disconnected"; +long wsrep_cluster_size = 0; +long wsrep_local_index = -1; +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; - wsp::Config_state *wsrep_config_state; -// Boolean denoting if server is in initial startup phase. This is needed -// to make sure that main thread waiting in wsrep_sst_wait() is signaled -// if there was no state gap on receiving first view event. -static my_bool wsrep_startup = TRUE; +wsrep_uuid_t local_uuid = WSREP_UUID_UNDEFINED; +wsrep_seqno_t local_seqno = WSREP_SEQNO_UNDEFINED; +wsp::node_status local_status; -static void wsrep_log_cb(wsrep_log_level_t level, const char *msg) { - switch (level) { - case WSREP_LOG_INFO: - sql_print_information("WSREP: %s", msg); - break; - case WSREP_LOG_WARN: - sql_print_warning("WSREP: %s", msg); - break; - case WSREP_LOG_ERROR: - case WSREP_LOG_FATAL: +/* + */ +Wsrep_schema *wsrep_schema= 0; + +static void wsrep_log_cb(wsrep::log::level level, const char *msg) +{ + /* + Silence all wsrep related logging from lib and provider if + wsrep is not enabled. + */ + if (WSREP_ON) + { + switch (level) { + case wsrep::log::info: + sql_print_information("WSREP: %s", msg); + break; + case wsrep::log::warning: + sql_print_warning("WSREP: %s", msg); + break; + case wsrep::log::error: sql_print_error("WSREP: %s", msg); break; - case WSREP_LOG_DEBUG: - if (wsrep_debug) sql_print_information ("[Debug] WSREP: %s", msg); - default: - break; + case wsrep::log::debug: + if (wsrep_debug) sql_print_information ("[Debug] WSREP: %s", msg); + default: + break; + } } } -void wsrep_log(void (*fun)(const char *, ...), const char *format, ...) +void wsrep_init_sidno(const wsrep::id& uuid) { - va_list args; - char msg[1024]; - va_start(args, format); - vsnprintf(msg, sizeof(msg) - 1, format, args); - va_end(args); - (fun)("WSREP: %s", msg); -} - - -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) -{ - char uuid_str[37]; - char msg[256]; - - wsrep_uuid_print (group_uuid, uuid_str, sizeof(uuid_str)); - snprintf (msg, 255, "WSREP: Group state: %s:%lld", - uuid_str, (long long)group_seqno); - wsrep_log_cb (level, msg); - - wsrep_uuid_print (node_uuid, uuid_str, sizeof(uuid_str)); - snprintf (msg, 255, "WSREP: Local state: %s:%lld", - uuid_str, (long long)node_seqno); - wsrep_log_cb (level, msg); -} - -#ifdef GTID_SUPPORT -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) + /* + Protocol versions starting from 4 use group gtid as it is. + For lesser protocol versions generate new Sid map entry from inverted + uuid. + */ + rpl_gtid sid; + if (wsrep_protocol_version >= 4) { - ltid_uuid.data[i] = ~wsrep_uuid.data[i]; + memcpy((void*)&sid, (const uchar*)uuid.data(),16); } - - sid.copy_from(ltid_uuid.data); + else + { + wsrep_uuid_t ltid_uuid; + for (size_t i= 0; i < sizeof(ltid_uuid.data); ++i) + { + ltid_uuid.data[i]= ~((const uchar*)uuid.data())[i]; + } + memcpy((void*)&sid, (const uchar*)ltid_uuid.data,16); + } +#ifdef GTID_SUPPORT global_sid_lock->wrlock(); wsrep_sidno= global_sid_map->add_sid(sid); WSREP_INFO("Initialized wsrep sidno %d", wsrep_sidno); global_sid_lock->unlock(); +#endif } -#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_member_status_t memb_status= wsrep_config_state->get_status(); - - if (memcmp(&cluster_uuid, &view->state_id.uuid, sizeof(wsrep_uuid_t))) - { - memcpy(&cluster_uuid, &view->state_id.uuid, sizeof(cluster_uuid)); - - wsrep_uuid_print (&cluster_uuid, cluster_uuid_str, - sizeof(cluster_uuid_str)); - } - - wsrep_cluster_conf_id= view->view; - wsrep_cluster_status= cluster_status_str[view->status]; - 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); - - /* Proceed further only if view is PRIMARY */ - if (WSREP_VIEW_PRIMARY != view->status) - { -#ifdef HAVE_QUERY_CACHE - // query cache must be initialised by now - query_cache.flush(); -#endif /* HAVE_QUERY_CACHE */ - - wsrep_ready_set(FALSE); - memb_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 */ - // WRONG! local_uuid should be the last primary configuration uuid we were - // a member of. local_seqno should be updated in commit calls. - // local_uuid= cluster_uuid; - // local_seqno= view->first - 1; - goto out; - } + DBUG_ASSERT(!wsrep_schema); - switch (view->proto_ver) + WSREP_INFO("wsrep_init_schema_and_SR %p", wsrep_schema); + if (!wsrep_schema) { - case 0: - case 1: - case 2: - case 3: - // version change - if (view->proto_ver != wsrep_protocol_version) - { - my_bool wsrep_ready_saved= wsrep_ready_get(); - wsrep_ready_set(FALSE); - WSREP_INFO("closing client connections for " - "protocol change %ld -> %d", - wsrep_protocol_version, view->proto_ver); - wsrep_close_client_connections(TRUE); - wsrep_protocol_version= view->proto_ver; - wsrep_ready_set(wsrep_ready_saved); - } - break; - default: - WSREP_ERROR("Unsupported application protocol version: %d", - view->proto_ver); - unireg_abort(1); - } - - if (view->state_gap) - { - 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_schema= new Wsrep_schema(); + if (wsrep_schema->init()) { - WSREP_DEBUG("[debug]: closing client connections for PRIM"); - wsrep_close_client_connections(FALSE); + WSREP_ERROR("Failed to init wsrep schema"); + unireg_abort(1); } + } +} - ssize_t const req_len= wsrep_sst_prepare (sst_req); +void wsrep_deinit_schema() +{ + delete wsrep_schema; + wsrep_schema= 0; +} - if (req_len < 0) +void wsrep_recover_sr_from_storage(THD *orig_thd) +{ + switch (wsrep_SR_store_type) + { + case WSREP_SR_STORE_TABLE: + if (!wsrep_schema) { - WSREP_ERROR("SST preparation failed: %zd (%s)", -req_len, - strerror(-req_len)); - memb_status= WSREP_MEMBER_UNDEFINED; + WSREP_ERROR("Wsrep schema not initialized when trying to recover " + "streaming transactions"); + unireg_abort(1); } - else + if (wsrep_schema->recover_sr_transactions(orig_thd)) { - assert(sst_req != NULL); - *sst_req_len= req_len; - memb_status= WSREP_MEMBER_JOINER; + WSREP_ERROR("Failed to recover SR transactions from schema"); + unireg_abort(1); } + break; + default: + /* */ + WSREP_ERROR("Unsupported wsrep SR store type: %lu", wsrep_SR_store_type); + unireg_abort(1); + break; } - 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) +} + +/** 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 (wsrep_before_SE()) + if (s.empty()) { - 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(); + s= ":"; } - else - { - local_uuid= cluster_uuid; - local_seqno= view->state_id.seqno; - } - /* Init storage engine XIDs from first view */ - wsrep_set_SE_checkpoint(local_uuid, local_seqno); -#ifdef GTID_SUPPORT - wsrep_init_sidno(local_uuid); -#endif /* GTID_SUPPORT */ - memb_status= WSREP_MEMBER_JOINED; - } - - // 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); + s += names[i]; + s += ":"; } } - if (wsrep_auto_increment_control) - { - global_system_variables.auto_increment_offset= view->my_idx + 1; - global_system_variables.auto_increment_increment= view->memb_num; - } + /* 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. */ - { /* capabilities may be updated on new configuration */ - uint64_t const caps(wsrep->capabilities (wsrep)); - - 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; - } + char* const previous= *str; -out: - if (view->status == WSREP_VIEW_PRIMARY) wsrep_startup= FALSE; - wsrep_config_state->set(memb_status, view); + *str= strdup(s.c_str()); - return WSREP_CB_SUCCESS; + if (previous != NULL) + { + free(previous); + } } -my_bool wsrep_ready_set (my_bool x) +/* 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_DEBUG("Setting wsrep_ready to %d", x); - if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort(); - my_bool ret= (wsrep_ready != x); - if (ret) - { - wsrep_ready= x; - mysql_cond_signal (&COND_wsrep_ready); - } - mysql_mutex_unlock (&LOCK_wsrep_ready); - return ret; } +/* + Wsrep is considered ready if + 1) Provider is not loaded (native mode) + 2) Server has reached synced state + 3) Server is in joiner mode and mysqldump SST method has been + specified + See Wsrep_server_service::log_state_change() for further details. + */ my_bool wsrep_ready_get (void) { if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort(); @@ -499,178 +430,67 @@ int wsrep_show_ready(THD *thd, SHOW_VAR *var, char *buff) return 0; } -// Wait until wsrep has reached ready state -void wsrep_ready_wait () +void wsrep_update_cluster_state_uuid(const char* uuid) { - if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort(); - while (!wsrep_ready) - { - WSREP_INFO("Waiting to reach ready state"); - mysql_cond_wait (&COND_wsrep_ready, &LOCK_wsrep_ready); - } - WSREP_INFO("ready state reached"); - mysql_mutex_unlock (&LOCK_wsrep_ready); + strncpy(cluster_uuid_str, uuid, sizeof(cluster_uuid_str) - 1); } -static void wsrep_synced_cb(void* app_ctx) +static void wsrep_init_position() { - WSREP_INFO("Synchronized with group, ready for connections"); - my_bool signal_main= wsrep_ready_set(TRUE); - wsrep_config_state->set(WSREP_MEMBER_SYNCED); - - if (signal_main) - { - wsrep_SE_init_grab(); - // 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_restart_slave_activated) - { - int rcode; - WSREP_INFO("MariaDB slave restart"); - wsrep_restart_slave_activated= FALSE; - - mysql_mutex_lock(&LOCK_active_mi); - if ((rcode = start_slave_threads(0, - 1 /* need mutex */, - 0 /* no wait for start*/, - active_mi, - master_info_file, - relay_log_info_file, - SLAVE_SQL))) - { - WSREP_WARN("Failed to create slave threads: %d", rcode); - } - mysql_mutex_unlock(&LOCK_active_mi); - - } } -static void wsrep_init_position() +/**************************************************************************** + Helpers for wsrep_init() + ****************************************************************************/ +static std::string wsrep_server_name() { - /* read XIDs from storage engines */ - wsrep_uuid_t uuid; - wsrep_seqno_t seqno; - wsrep_get_SE_checkpoint(uuid, seqno); - - if (!memcmp(&uuid, &WSREP_UUID_UNDEFINED, sizeof(wsrep_uuid_t))) - { - WSREP_INFO("Read nil XID from storage engines, skipping position init"); - return; - } - - 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); - - if (!memcmp(&local_uuid, &WSREP_UUID_UNDEFINED, sizeof(local_uuid)) && - local_seqno == WSREP_SEQNO_UNDEFINED) - { - // Initial state - local_uuid= uuid; - local_seqno= seqno; - } - else if (memcmp(&local_uuid, &uuid, sizeof(local_uuid)) || - local_seqno != seqno) - { - WSREP_WARN("Initial position was provided by configuration or SST, " - "avoiding override"); - } + std::string ret(wsrep_node_name ? wsrep_node_name : ""); + return ret; } -extern char* my_bind_addr_str; - -int wsrep_init() +static std::string wsrep_server_id() { - int rcode= -1; - DBUG_ASSERT(wsrep_inited == 0); - - if (strcmp(wsrep_start_position, WSREP_START_POSITION_ZERO) && - wsrep_start_position_init(wsrep_start_position)) - { - return 1; - } - - wsrep_sst_auth_init(); - - wsrep_ready_set(FALSE); - assert(wsrep_provider); - - wsrep_init_position(); - - if ((rcode= wsrep_load(wsrep_provider, &wsrep, wsrep_log_cb)) != WSREP_OK) - { - if (strcasecmp(wsrep_provider, WSREP_NONE)) - { - WSREP_ERROR("wsrep_load(%s) failed: %s (%d). Reverting to no provider.", - wsrep_provider, strerror(rcode), rcode); - strcpy((char*)wsrep_provider, WSREP_NONE); // damn it's a dirty hack - return wsrep_init(); - } - else /* this is for recursive call above */ - { - WSREP_ERROR("Could not revert to no provider: %s (%d). Need to abort.", - strerror(rcode), rcode); - unireg_abort(1); - } - } + /* using empty server_id, which enables view change handler to + set final server_id later on + */ + std::string ret(""); + return ret; +} - if (!WSREP_PROVIDER_EXISTS) - { - // enable normal operation in case no provider is specified - wsrep_ready_set(TRUE); - wsrep_inited= 1; - global_system_variables.wsrep_on = 0; - wsrep_init_args args; - args.logger_cb = wsrep_log_cb; - args.options = (wsrep_provider_options) ? - wsrep_provider_options : ""; - rcode = wsrep->init(wsrep, &args); - if (rcode) - { - DBUG_PRINT("wsrep",("wsrep::init() failed: %d", rcode)); - WSREP_ERROR("wsrep::init() failed: %d, must shutdown", rcode); - wsrep->free(wsrep); - free(wsrep); - wsrep = NULL; - } - return rcode; - } - else - { - global_system_variables.wsrep_on = 1; - strncpy(provider_name, - wsrep->provider_name, sizeof(provider_name) - 1); - strncpy(provider_version, - wsrep->provider_version, sizeof(provider_version) - 1); - strncpy(provider_vendor, - wsrep->provider_vendor, sizeof(provider_vendor) - 1); - } +static std::string wsrep_server_node_address() +{ + std::string ret; if (!wsrep_data_home_dir || strlen(wsrep_data_home_dir) == 0) - wsrep_data_home_dir = mysql_real_data_home; + 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; if (!wsrep_node_address || !strcmp(wsrep_node_address, "")) { - size_t const ret= wsrep_guess_ip(node_addr, node_addr_max); - if (!(ret > 0 && ret < node_addr_max)) + char node_addr[512]= {0, }; + const size_t node_addr_max= sizeof(node_addr) - 1; + size_t guess_ip_ret= wsrep_guess_ip(node_addr, node_addr_max); + if (!(guess_ip_ret > 0 && guess_ip_ret < node_addr_max)) { WSREP_WARN("Failed to guess base node address. Set it explicitly via " "wsrep_node_address."); - node_addr[0]= '\0'; + } + else + { + ret= node_addr; } } else { - strncpy(node_addr, wsrep_node_address, node_addr_max); + ret= wsrep_node_address; } + return ret; +} - /* Initialize node's incoming address */ +static std::string wsrep_server_incoming_address() +{ + std::string ret; + const std::string node_addr(wsrep_server_node_address()); char inc_addr[512]= { 0, }; size_t const inc_addr_max= sizeof (inc_addr); @@ -685,7 +505,8 @@ int wsrep_init() bool is_ipv6= false; unsigned int my_bind_ip= INADDR_ANY; // default if not set - if (my_bind_addr_str && strlen(my_bind_addr_str)) + if (my_bind_addr_str && strlen(my_bind_addr_str) && + strcmp(my_bind_addr_str, "*") != 0) { my_bind_ip= wsrep_check_ip(my_bind_addr_str, &is_ipv6); } @@ -704,22 +525,28 @@ int wsrep_init() } else /* mysqld binds to 0.0.0.0, try taking IP from wsrep_node_address. */ { - size_t const node_addr_len= strlen(node_addr); - if (node_addr_len > 0) + if (node_addr.size()) { - wsp::Address addr(node_addr); - - if (!addr.is_valid()) + size_t const ip_len= wsrep_host_len(node_addr.c_str(), node_addr.size()); + if (ip_len + 7 /* :55555\0 */ < inc_addr_max) { - WSREP_DEBUG("Could not parse node address : %s", node_addr); - WSREP_WARN("Guessing address for incoming client connections failed. " - "Try setting wsrep_node_incoming_address explicitly."); - goto done; + memcpy (inc_addr, node_addr.c_str(), ip_len); + snprintf(inc_addr + ip_len, inc_addr_max - ip_len, ":%u", + (int)mysqld_port); } + else + { + WSREP_WARN("Guessing address for incoming client connections: " + "address too long."); + inc_addr[0]= '\0'; + } + } - const char *fmt= (addr.is_ipv6()) ? "[%s]:%u" : "%s:%u"; - snprintf(inc_addr, inc_addr_max, fmt, addr.get_address(), - (int) mysqld_port); + if (!strlen(inc_addr)) + { + WSREP_WARN("Guessing address for incoming client connections failed. " + "Try setting wsrep_node_incoming_address explicitly."); + WSREP_INFO("Node addr: %s", node_addr.c_str()); } } } @@ -743,52 +570,178 @@ int wsrep_init() snprintf(inc_addr, inc_addr_max, fmt, addr.get_address(), port); } + + done: + ret= wsrep_node_incoming_address; + return ret; +} -done: - struct wsrep_init_args wsrep_args; +static std::string wsrep_server_working_dir() +{ + std::string ret; + if (!wsrep_data_home_dir || strlen(wsrep_data_home_dir) == 0) + { + ret= mysql_real_data_home; + } + else + { + ret= wsrep_data_home_dir; + } + return ret; +} - struct wsrep_gtid const state_id = { local_uuid, local_seqno }; +static wsrep::gtid wsrep_server_initial_position() +{ + wsrep::gtid ret; + WSREP_INFO("Server initial position: %s", wsrep_start_position); + std::istringstream is(wsrep_start_position); + is >> ret; + return ret; +} - wsrep_args.data_dir = wsrep_data_home_dir; - wsrep_args.node_name = (wsrep_node_name) ? wsrep_node_name : ""; - wsrep_args.node_address = node_addr; - wsrep_args.node_incoming = inc_addr; - wsrep_args.options = (wsrep_provider_options) ? - wsrep_provider_options : ""; - wsrep_args.proto_ver = wsrep_max_protocol_version; +/* + Intitialize provider specific status variables + */ +static void wsrep_init_provider_status_variables() +{ + const wsrep::provider& provider= + Wsrep_server_state::instance().provider(); + strncpy(provider_name, + provider.name().c_str(), sizeof(provider_name) - 1); + strncpy(provider_version, + provider.version().c_str(), sizeof(provider_version) - 1); + strncpy(provider_vendor, + provider.vendor().c_str(), sizeof(provider_vendor) - 1); +} + +int wsrep_init_server() +{ + wsrep::log::logger_fn(wsrep_log_cb); + try + { + std::string server_name; + std::string server_id; + std::string node_address; + std::string incoming_address; + std::string working_dir; + wsrep::gtid initial_position; + + server_name= wsrep_server_name(); + server_id= wsrep_server_id(); + node_address= wsrep_server_node_address(); + incoming_address= wsrep_server_incoming_address(); + working_dir= wsrep_server_working_dir(); + initial_position= wsrep_server_initial_position(); + + Wsrep_server_state::init_once(server_name, + incoming_address, + node_address, + working_dir, + initial_position, + wsrep_max_protocol_version); + } + catch (const wsrep::runtime_error& e) + { + WSREP_ERROR("Failed to init wsrep server %s", e.what()); + return 1; + } + catch (const std::exception& e) + { + WSREP_ERROR("Failed to init wsrep server %s", e.what()); + } + return 0; +} - wsrep_args.state_id = &state_id; +void wsrep_init_globals() +{ + wsrep_init_sidno(Wsrep_server_state::instance().connected_gtid().id()); + wsrep_init_schema(); + if (WSREP_ON) + { + Wsrep_server_state::instance().initialized(); + } +} - wsrep_args.logger_cb = wsrep_log_cb; - wsrep_args.view_handler_cb = wsrep_view_handler_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; +void wsrep_deinit_server() +{ + wsrep_deinit_schema(); + Wsrep_server_state::destroy(); +} - rcode = wsrep->init(wsrep, &wsrep_args); +int wsrep_init() +{ + assert(wsrep_provider); - if (rcode) + wsrep_init_position(); + wsrep_sst_auth_init(); + + if (strlen(wsrep_provider)== 0 || + !strcmp(wsrep_provider, WSREP_NONE)) { - DBUG_PRINT("wsrep",("wsrep::init() failed: %d", rcode)); - WSREP_ERROR("wsrep::init() failed: %d, must shutdown", rcode); - wsrep->free(wsrep); - free(wsrep); - wsrep = NULL; - } else { - wsrep_inited= 1; + // enable normal operation in case no provider is specified + global_system_variables.wsrep_on= 0; + int err= Wsrep_server_state::instance().load_provider(wsrep_provider, wsrep_provider_options ? wsrep_provider_options : ""); + if (err) + { + DBUG_PRINT("wsrep",("wsrep::init() failed: %d", err)); + WSREP_ERROR("wsrep::init() failed: %d, must shutdown", err); + } + else + { + wsrep_init_provider_status_variables(); + } + return err; } - return rcode; -} + global_system_variables.wsrep_on= 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; + + if (Wsrep_server_state::instance().load_provider(wsrep_provider, + wsrep_provider_options)) + { + WSREP_ERROR("Failed to load provider"); + return 1; + } + + 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 (%llu). 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_server_state::instance().unload_provider(); + return 1; + } + wsrep_inited= 1; + + wsrep_init_provider_status_variables(); + wsrep_capabilities_export(Wsrep_server_state::instance().provider().capabilities(), + &wsrep_provider_capabilities); + + WSREP_DEBUG("SR storage init for: %s", + (wsrep_SR_store_type == WSREP_SR_STORE_TABLE) ? "table" : "void"); + return 0; +} /* Initialize wsrep thread LOCKs and CONDs */ void wsrep_thr_init() { DBUG_ENTER("wsrep_thr_init"); - wsrep_config_state = new wsp::Config_state; + wsrep_config_state= new wsp::Config_state; #ifdef HAVE_PSI_INTERFACE mysql_mutex_register("sql", wsrep_mutexes, array_elements(wsrep_mutexes)); mysql_cond_register("sql", wsrep_conds, array_elements(wsrep_conds)); @@ -801,25 +754,24 @@ 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); DBUG_VOID_RETURN; } -void wsrep_init_startup (bool first) +void wsrep_init_startup (bool sst_first) { if (wsrep_init()) unireg_abort(1); - 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); + wsrep_thr_lock_init(wsrep_thd_is_BF, wsrep_thd_bf_abort, + wsrep_debug, wsrep_convert_LOCK_to_trx, wsrep_on); /* Pre-initialize global_system_variables.table_plugin with a dummy engine @@ -838,28 +790,54 @@ void wsrep_init_startup (bool first) /* Skip replication start if no cluster address */ if (!wsrep_cluster_address || wsrep_cluster_address[0] == 0) return; - if (first) wsrep_sst_grab(); // do it so we can wait for SST below - + /* + Read value of wsrep_new_cluster before wsrep_start_replication(), + the value is reset to FALSE inside wsrep_start_replication. + */ if (!wsrep_start_replication()) unireg_abort(1); wsrep_create_rollbacker(); wsrep_create_appliers(1); - if (first && !wsrep_sst_wait()) unireg_abort(1);// wait until SST is completed + Wsrep_server_state& server_state= Wsrep_server_state::instance(); + /* + If the SST happens before server initialization, wait until the server + state reaches initializing. This indicates that + either SST was not necessary or SST has been delivered. + + With mysqldump SST (!sst_first) wait until the server reaches + joiner state and procedd to accepting connections. + */ + if (sst_first) + { + server_state.wait_until_state(Wsrep_server_state::s_initializing); + } + else + { + server_state.wait_until_state(Wsrep_server_state::s_joiner); + } } void wsrep_deinit(bool free_options) { DBUG_ASSERT(wsrep_inited == 1); - wsrep_unload(wsrep); - wsrep= 0; + WSREP_DEBUG("wsrep_deinit"); + + Wsrep_server_state::instance().unload_provider(); provider_name[0]= '\0'; provider_version[0]= '\0'; provider_vendor[0]= '\0'; wsrep_inited= 0; + if (wsrep_provider_capabilities != NULL) + { + char* p= wsrep_provider_capabilities; + wsrep_provider_capabilities= NULL; + free(p); + } + if (free_options) { wsrep_sst_auth_free(); @@ -871,28 +849,37 @@ 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); + 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]; - 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)); @@ -900,43 +887,60 @@ 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); + wsrep::gtid gtid= wsrep_get_SE_checkpoint(); + std::ostringstream oss; + oss << gtid; + WSREP_INFO("Recovered position: %s", oss.str().c_str()); } void wsrep_stop_replication(THD *thd) { WSREP_INFO("Stop replication"); - if (!wsrep) + if (Wsrep_server_state::instance().state() != + Wsrep_server_state::s_disconnected) { - WSREP_INFO("Provider was not loaded, in stop replication"); - return; + WSREP_DEBUG("Disconnect provider"); + Wsrep_server_state::instance().disconnect(); + Wsrep_server_state::instance().wait_until_state(Wsrep_server_state::s_disconnected); } - /* disconnect from group first to get wsrep_ready == FALSE */ - WSREP_DEBUG("Provider disconnect"); - wsrep->disconnect(wsrep); + /* 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; +} - wsrep_connected= FALSE; +void wsrep_shutdown_replication() +{ + WSREP_INFO("Shutdown replication"); + if (Wsrep_server_state::instance().state() != wsrep::server_state::s_disconnected) + { + WSREP_DEBUG("Disconnect provider"); + Wsrep_server_state::instance().disconnect(); + Wsrep_server_state::instance().wait_until_state(Wsrep_server_state::s_disconnected); + } wsrep_close_client_connections(TRUE); /* wait until appliers have stopped */ - wsrep_wait_appliers_close(thd); + wsrep_wait_appliers_close(NULL); + node_uuid= WSREP_UUID_UNDEFINED; - return; + /* Undocking the thread specific data. */ + my_pthread_setspecific_ptr(THR_THD, NULL); } bool wsrep_start_replication() { - wsrep_status_t rcode; - - /* wsrep provider must be loaded. */ - DBUG_ASSERT(wsrep); + int rcode; + WSREP_DEBUG("wsrep_start_replication"); /* if provider is trivial, don't even try to connect, @@ -945,34 +949,27 @@ bool wsrep_start_replication() if (!WSREP_PROVIDER_EXISTS) { // enable normal operation in case no provider is specified - wsrep_ready_set(TRUE); return true; } if (!wsrep_cluster_address || wsrep_cluster_address[0]== 0) { // if provider is non-trivial, but no address is specified, wait for address - wsrep_ready_set(FALSE); return true; } - bool const bootstrap= wsrep_new_cluster; + bool const bootstrap(TRUE == wsrep_new_cluster); + wsrep_new_cluster= FALSE; WSREP_INFO("Start replication"); - if (wsrep_new_cluster) + if ((rcode= Wsrep_server_state::instance().connect( + wsrep_cluster_name, + wsrep_cluster_address, + wsrep_sst_donor, + bootstrap))) { - WSREP_INFO("'wsrep-new-cluster' option used, bootstrapping the cluster"); - wsrep_new_cluster= false; - } - - if ((rcode = wsrep->connect(wsrep, - wsrep_cluster_name, - wsrep_cluster_address, - wsrep_sst_donor, - bootstrap))) - { - DBUG_PRINT("wsrep",("wsrep->connect(%s) failed: %d", + DBUG_PRINT("wsrep",("wsrep_ptr->connect(%s) failed: %d", wsrep_cluster_address, rcode)); WSREP_ERROR("wsrep::connect(%s) failed: %d", wsrep_cluster_address, rcode); @@ -980,15 +977,12 @@ bool wsrep_start_replication() } else { - wsrep_connected= TRUE; - - char* opts= wsrep->options_get(wsrep); - if (opts) + try { - wsrep_provider_options_init(opts); - free(opts); + std::string opts= Wsrep_server_state::instance().provider().options(); + wsrep_provider_options_init(opts.c_str()); } - else + catch (const wsrep::runtime_error&) { WSREP_WARN("Failed to get wsrep options"); } @@ -999,40 +993,50 @@ 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_thd_data); + ret= (thd->variables.wsrep_sync_wait & mask) && + thd->wsrep_client_thread && 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_sync_wait_gtid.seqno == WSREP_SEQNO_UNDEFINED; + thd->wsrep_trx().state() != + wsrep::transaction::s_replaying && + thd->wsrep_cs().sync_wait_gtid().is_undefined(); + mysql_mutex_unlock(&thd->LOCK_thd_data); + return ret; } bool wsrep_sync_wait (THD* thd, uint mask) { if (wsrep_must_sync_wait(thd, mask)) { - WSREP_DEBUG("wsrep_sync_wait: thd->variables.wsrep_sync_wait = %u, mask = %u", - 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); - - if (unlikely(WSREP_OK != ret)) + WSREP_DEBUG("wsrep_sync_wait: thd->variables.wsrep_sync_wait= %u, " + "mask= %u, thd->variables.wsrep_on= %d", + thd->variables.wsrep_sync_wait, mask, + thd->variables.wsrep_on); + /* + This allows autocommit SELECTs and a first SELECT after SET AUTOCOMMIT=0 + TODO: modify to check if thd has locked any rows. + */ + if (thd->wsrep_cs().sync_wait(-1)) { const char* msg; int err; - // Possibly relevant error codes: - // ER_CHECKREAD, ER_ERROR_ON_READ, ER_INVALID_DEFAULT, ER_EMPTY_QUERY, - // ER_FUNCTION_NOT_DEFINED, ER_NOT_ALLOWED_COMMAND, ER_NOT_SUPPORTED_YET, - // ER_FEATURE_DISABLED, ER_QUERY_INTERRUPTED + /* + Possibly relevant error codes: + ER_CHECKREAD, ER_ERROR_ON_READ, ER_INVALID_DEFAULT, ER_EMPTY_QUERY, + ER_FUNCTION_NOT_DEFINED, ER_NOT_ALLOWED_COMMAND, ER_NOT_SUPPORTED_YET, + ER_FEATURE_DISABLED, ER_QUERY_INTERRUPTED + */ - switch (ret) + switch (thd->wsrep_cs().current_error()) { - case WSREP_NOT_IMPLEMENTED: + case wsrep::e_not_supported_error: msg= "synchronous reads by wsrep backend. " - "Please unset wsrep_causal_reads variable."; + "Please unset wsrep_causal_reads variable."; err= ER_NOT_SUPPORTED_YET; break; default: @@ -1050,6 +1054,27 @@ bool wsrep_sync_wait (THD* thd, uint mask) return false; } +enum wsrep::provider::status +wsrep_sync_wait_upto (THD* thd, + wsrep_gtid_t* upto, + int timeout) +{ + DBUG_ASSERT(upto); + enum wsrep::provider::status ret; + if (upto) + { + wsrep::gtid upto_gtid(wsrep::id(upto->uuid.data, sizeof(upto->uuid.data)), + wsrep::seqno(upto->seqno)); + ret= Wsrep_server_state::instance().wait_for_gtid(upto_gtid, timeout); + } + else + { + ret= Wsrep_server_state::instance().causal_read(timeout).second; + } + WSREP_DEBUG("wsrep_sync_wait_upto: %d", ret); + return ret; +} + void wsrep_keys_free(wsrep_key_arr_t* key_arr) { for (size_t i= 0; i < key_arr->keys_len; ++i) @@ -1061,7 +1086,6 @@ void wsrep_keys_free(wsrep_key_arr_t* key_arr) key_arr->keys_len= 0; } - /*! * @param db Database string * @param table Table string @@ -1073,9 +1097,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; @@ -1087,11 +1111,11 @@ static bool wsrep_prepare_key_for_isolation(const char* db, case 1: case 2: case 3: + case 4: { *key_len= 0; if (db) { - // sql_print_information("%s.%s", db, table); key[*key_len].ptr= db; key[*key_len].len= strlen(db); ++(*key_len); @@ -1105,26 +1129,23 @@ 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; -} + return true; +} static bool wsrep_prepare_key_for_isolation(const char* db, const char* table, wsrep_key_arr_t* ka) { wsrep_key_t* tmp; - - if (!ka->keys) - tmp= (wsrep_key_t*)my_malloc((ka->keys_len + 1) * sizeof(wsrep_key_t), - MYF(0)); - else - tmp= (wsrep_key_t*)my_realloc(ka->keys, - (ka->keys_len + 1) * sizeof(wsrep_key_t), - MYF(0)); - + tmp= (wsrep_key_t*)my_realloc(ka->keys, + (ka->keys_len + 1) * sizeof(wsrep_key_t), + MYF(MY_ALLOW_ZERO_PTR)); if (!tmp) { WSREP_ERROR("Can't allocate memory for key_array"); @@ -1150,7 +1171,6 @@ static bool wsrep_prepare_key_for_isolation(const char* db, return true; } - static bool wsrep_prepare_keys_for_alter_add_fk(const char* child_table_db, Alter_info* alter_info, wsrep_key_arr_t* ka) @@ -1177,7 +1197,6 @@ static bool wsrep_prepare_keys_for_alter_add_fk(const char* child_table_db, return true; } - static bool wsrep_prepare_keys_for_isolation(THD* thd, const char* db, const char* table, @@ -1205,16 +1224,19 @@ static bool wsrep_prepare_keys_for_isolation(THD* thd, if (!wsrep_prepare_keys_for_alter_add_fk(table_list->db.str, alter_info, ka)) goto err; } - return false; err: - wsrep_keys_free(ka); - return true; + wsrep_keys_free(ka); + return true; } +/* + * Prepare key list from db/table and table_list + * + * Return zero in case of success, 1 in case of failure. + */ -/* Prepare key list from db/table and table_list */ bool wsrep_prepare_keys_for_isolation(THD* thd, const char* db, const char* table, @@ -1224,7 +1246,6 @@ bool wsrep_prepare_keys_for_isolation(THD* thd, return wsrep_prepare_keys_for_isolation(thd, db, table, table_list, NULL, ka); } - 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) @@ -1236,37 +1257,110 @@ bool wsrep_prepare_key(const uchar* cache_key, size_t cache_key_len, { case 0: { - key[0].ptr = cache_key; - key[0].len = cache_key_len; + key[0].ptr= cache_key; + key[0].len= cache_key_len; - *key_len = 1; + *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[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[1].ptr= cache_key + strlen( (char*)cache_key ) + 1; + key[1].len= strlen( (char*)(key[1].ptr) ); - *key_len = 2; + *key_len= 2; break; } default: return false; } - key[*key_len].ptr = row_id; - key[*key_len].len = row_id_len; + key[*key_len].ptr= row_id; + key[*key_len].len= row_id_len; ++(*key_len); return true; } +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) +{ + + return wsrep_prepare_key(cache_key, cache_key_len, row_id, row_id_len, key, key_len); +} + +wsrep::key wsrep_prepare_key_for_toi(const char* db, const char* table, + enum wsrep::key::type type) +{ + wsrep::key ret(type); + DBUG_ASSERT(db); + ret.append_key_part(db, strlen(db)); + if (table) ret.append_key_part(table, strlen(table)); + return ret; +} +wsrep::key_array +wsrep_prepare_keys_for_alter_add_fk(const char* child_table_db, + Alter_info* alter_info) + +{ + wsrep::key_array ret; + Key *key; + List_iterator<Key> key_iterator(alter_info->key_list); + while ((key= key_iterator++)) + { + if (key->type == Key::FOREIGN_KEY) + { + Foreign_key *fk_key= (Foreign_key *)key; + const char *db_name= fk_key->ref_db.str; + const char *table_name= fk_key->ref_table.str; + if (!db_name) + { + db_name= child_table_db; + } + ret.push_back(wsrep_prepare_key_for_toi(db_name, table_name, + wsrep::key::exclusive)); + } + } + return ret; +} + +wsrep::key_array wsrep_prepare_keys_for_toi(const char* db, + const char* table, + const TABLE_LIST* table_list, + Alter_info* alter_info) +{ + wsrep::key_array ret; + if (db || table) + { + ret.push_back(wsrep_prepare_key_for_toi(db, table, wsrep::key::exclusive)); + } + for (const TABLE_LIST* table= table_list; table; table= table->next_global) + { + ret.push_back(wsrep_prepare_key_for_toi(table->db.str, table->table_name.str, + wsrep::key::exclusive)); + } + if (alter_info && (alter_info->flags & ALTER_ADD_FOREIGN_KEY)) + { + wsrep::key_array fk(wsrep_prepare_keys_for_alter_add_fk(table_list->db.str, alter_info)); + if (!fk.empty()) + { + ret.insert(ret.end(), fk.begin(), fk.end()); + } + } + return ret; +} /* * Construct Query_log_Event from thd query and serialize it * into buffer. @@ -1277,7 +1371,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; @@ -1365,7 +1459,7 @@ create_view_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; - TABLE_LIST *views = first_table; + TABLE_LIST *views= first_table; LEX_USER *definer; String buff; const LEX_CSTRING command[3]= @@ -1390,16 +1484,16 @@ create_view_query(THD *thd, uchar** buf, size_t* buf_len) if (definer) { - views->definer.user = definer->user; - views->definer.host = definer->host; + views->definer.user= definer->user; + views->definer.host= definer->host; } else { WSREP_ERROR("Failed to get DEFINER for VIEW."); return 1; } - views->algorithm = lex->create_view->algorithm; - views->view_suid = lex->create_view->suid; - views->with_check = lex->create_view->check; + views->algorithm = lex->create_view->algorithm; + views->view_suid = lex->create_view->suid; + views->with_check = lex->create_view->check; view_store_options(thd, views, &buff); buff.append(STRING_WITH_LEN("VIEW ")); @@ -1425,12 +1519,8 @@ create_view_query(THD *thd, uchar** buf, size_t* buf_len) buff.append(')'); } buff.append(STRING_WITH_LEN(" AS ")); - //buff.append(views->source.str, views->source.length); buff.append(thd->lex->create_view->select.str, thd->lex->create_view->select.length); - //int errcode= query_error_code(thd, TRUE); - //if (thd->binlog_query(THD::STMT_QUERY_TYPE, - // buff.ptr(), buff.length(), FALSE, FALSE, FALSE, errcod return wsrep_to_buf_helper(thd, buff.ptr(), buff.length(), buf, buf_len); } @@ -1496,8 +1586,7 @@ static int wsrep_drop_table_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_trigger_query(THD *thd, uchar** buf, size_t* buf_len); /* Decide if statement should run in TOI. @@ -1577,6 +1666,7 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table, } } +#if UNUSED /* 323f269d4099 (Jan Lindström 2018-07-19) */ static const char* wsrep_get_query_or_msg(const THD* thd) { switch(thd->lex->sql_command) @@ -1589,58 +1679,70 @@ static const char* wsrep_get_query_or_msg(const THD* thd) return "REVOKE"; case SQLCOM_SET_OPTION: if (thd->lex->definer) - return "SET PASSWORD"; + return "SET PASSWORD"; /* fallthrough */ default: return thd->query(); } } +#endif //UNUSED -/* - returns: - 0: statement was replicated as TOI - 1: TOI replication was skipped - -1: TOI replication failed - */ -static int wsrep_TOI_begin(THD *thd, const char *db_, const char *table_, - const TABLE_LIST* table_list, - Alter_info* alter_info) +static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len) { - wsrep_status_t ret(WSREP_WARNING); - uchar* buf(0); - size_t buf_len(0); - int buf_err; - int rc= 0; + String log_query; + sp_head *sp= thd->lex->sphead; + sql_mode_t saved_mode= thd->variables.sql_mode; + String retstr(64); + LEX_CSTRING returns= empty_clex_str; + retstr.set_charset(system_charset_info); - if (wsrep_can_run_in_toi(thd, db_, table_, table_list) == false) + log_query.set_charset(system_charset_info); + + if (sp->m_handler->type() == TYPE_ENUM_FUNCTION) { - WSREP_DEBUG("No TOI for %s", WSREP_QUERY(thd)); + sp_returns_type(thd, retstr, sp); + returns= retstr.lex_cstring(); + } + if (sp->m_handler-> + show_create_sp(thd, &log_query, + sp->m_explicit_name ? sp->m_db : null_clex_str, + sp->m_name, sp->m_params, returns, + sp->m_body, sp->chistics(), + thd->lex->definer[0], + thd->lex->create_info, + saved_mode)) + { + WSREP_WARN("SP create string failed: schema: %s, query: %s", + thd->get_db(), thd->query()); return 1; } - WSREP_DEBUG("TO BEGIN: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd), - thd->wsrep_exec_mode, wsrep_get_query_or_msg(thd)); + return wsrep_to_buf_helper(thd, log_query.ptr(), log_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: - buf_err= create_view_query(thd, &buf, &buf_len); + 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); + err= wsrep_create_sp(thd, buf, buf_len); break; case SQLCOM_CREATE_TRIGGER: - buf_err= wsrep_create_trigger_query(thd, &buf, &buf_len); + err= wsrep_create_trigger_query(thd, buf, buf_len); break; case SQLCOM_CREATE_EVENT: - buf_err= wsrep_create_event_query(thd, &buf, &buf_len); + err= wsrep_create_event_query(thd, buf, buf_len); break; case SQLCOM_ALTER_EVENT: - buf_err= wsrep_alter_event_query(thd, &buf, &buf_len); + err= wsrep_alter_event_query(thd, buf, buf_len); break; case SQLCOM_DROP_TABLE: - buf_err= wsrep_drop_table_query(thd, &buf, &buf_len); + err= wsrep_drop_table_query(thd, buf, buf_len); break; case SQLCOM_CREATE_ROLE: if (sp_process_definer(thd)) @@ -1649,169 +1751,212 @@ static int wsrep_TOI_begin(THD *thd, const char *db_, const char *table_, } /* fallthrough */ default: - buf_err= wsrep_to_buf_helper(thd, thd->query(), thd->query_length(), - &buf, &buf_len); + err= wsrep_to_buf_helper(thd, thd->query(), thd->query_length(), buf, + buf_len); break; } - 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, alter_info, &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); - rc= -1; - } - else { - /* 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"); - rc= 1; + return err; +} + +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::client_state& cs(thd->wsrep_cs()); + int const ret= cs.leave_toi(); + if (ret) + { + WSREP_ERROR("Leaving critical section for failed TOI failed: thd: %lld, " + "schema: %s, SQL: %s, rcode: %d wsrep_error: %s", + (long long)thd->real_id, thd->db.str, + thd->query(), ret, wsrep::to_c_string(cs.current_error())); + goto fail; + } } - if (buf) my_free(buf); - return rc; + return; +fail: + WSREP_ERROR("Failed to release TOI resources. Need to abort."); + unireg_abort(1); } -static void wsrep_TOI_end(THD *thd) { - wsrep_status_t ret; - wsrep_to_isolation--; - WSREP_DEBUG("TO END: %lld, %d: %s", (long long)wsrep_thd_trx_seqno(thd), - thd->wsrep_exec_mode, wsrep_get_query_or_msg(thd)); +/* + returns: + 0: statement was replicated as TOI + 1: TOI replication was skipped + -1: TOI replication failed + */ +static int wsrep_TOI_begin(THD *thd, const char *db, const char *table, + const TABLE_LIST* table_list, + Alter_info* alter_info) +{ + DBUG_ASSERT(thd->variables.wsrep_OSU_method == WSREP_OSU_TOI); - 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)); + WSREP_DEBUG("TOI Begin"); + if (wsrep_can_run_in_toi(thd, db, table, table_list) == false) + { + WSREP_DEBUG("No TOI for %s", WSREP_QUERY(thd)); + return 1; } - else { - WSREP_WARN("TO isolation end failed for: %d, schema: %s, sql: %s", - ret, - thd->get_db(), - (thd->query()) ? thd->query() : "void"); + + uchar* buf= 0; + size_t buf_len(0); + int buf_err; + int rc; + + 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 }; -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() ); + wsrep::key_array key_array= + wsrep_prepare_keys_for_toi(db, table, table_list, alter_info); - ret = wsrep->desync(wsrep); - if (ret != WSREP_OK) + if (thd->has_read_only_protection()) { - WSREP_WARN("RSU desync failed %d for schema: %s, query: %s", - ret, thd->get_db(), thd->query()); - my_error(ER_LOCK_DEADLOCK, MYF(0)); - return(ret); + /* non replicated DDL, affecting temporary tables only */ + WSREP_DEBUG("TO isolation skipped, sql: %s." + "Only temporary tables affected.", + WSREP_QUERY(thd)); + if (buf) my_free(buf); + return -1; } - mysql_mutex_lock(&LOCK_wsrep_replaying); - wsrep_replaying++; - mysql_mutex_unlock(&LOCK_wsrep_replaying); + thd_proc_info(thd, "acquiring total order isolation"); - if (wsrep_wait_committing_connections_close(5000)) + wsrep::client_state& cs(thd->wsrep_cs()); + int ret= cs.enter_toi(key_array, + wsrep::const_buffer(buff.ptr, buff.len), + wsrep::provider::flag::start_transaction | + wsrep::provider::flag::commit); + + if (ret) { - /* no can do, bail out from DDL */ - WSREP_WARN("RSU failed due to pending transactions, schema: %s, query %s", - thd->get_db(), thd->query()); - mysql_mutex_lock(&LOCK_wsrep_replaying); - wsrep_replaying--; - mysql_mutex_unlock(&LOCK_wsrep_replaying); + DBUG_ASSERT(cs.current_error()); + WSREP_DEBUG("to_execute_start() failed for %llu: %s, seqno: %lld", + thd->thread_id, WSREP_QUERY(thd), + (long long)wsrep_thd_trx_seqno(thd)); - ret = wsrep->resync(wsrep); - if (ret != WSREP_OK) + /* jump to error handler in mysql_execute_command() */ + switch (cs.current_error()) { - WSREP_WARN("resync failed %d for schema: %s, query: %s", - ret, thd->get_db(), thd->query()); + case wsrep::e_size_exceeded_error: + 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."); + } } - - my_error(ER_LOCK_DEADLOCK, MYF(0)); - return(1); + rc= -1; } - - wsrep_seqno_t seqno = wsrep->pause(wsrep); - if (seqno == WSREP_SEQNO_UNDEFINED) - { - WSREP_WARN("pause failed %lld for schema: %s, query: %s", (long long)seqno, - thd->get_db(), thd->query()); - return(1); + else { + ++wsrep_to_isolation; + rc= 0; } - WSREP_DEBUG("paused at %lld", (long long)seqno); - thd->variables.wsrep_on = 0; - return 0; -} -static void wsrep_RSU_end(THD *thd) -{ - wsrep_status_t ret(WSREP_WARNING); - WSREP_DEBUG("RSU END: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd), - thd->wsrep_exec_mode, thd->query() ); + if (buf) my_free(buf); + if (rc) wsrep_TOI_begin_failed(thd, NULL); - mysql_mutex_lock(&LOCK_wsrep_replaying); - wsrep_replaying--; - mysql_mutex_unlock(&LOCK_wsrep_replaying); + return rc; +} - ret = wsrep->resume(wsrep); - if (ret != WSREP_OK) +static void wsrep_TOI_end(THD *thd) { + int ret; + wsrep_to_isolation--; + wsrep::client_state& client_state(thd->wsrep_cs()); + DBUG_ASSERT(wsrep_thd_is_local_toi(thd)); + WSREP_DEBUG("TO END: %lld: %s", client_state.toi_meta().seqno().get(), + WSREP_QUERY(thd)); + + if (wsrep_thd_is_local_toi(thd)) { - WSREP_WARN("resume failed %d for schema: %s, query: %s", ret, - thd->get_db(), thd->query()); + wsrep_set_SE_checkpoint(client_state.toi_meta().gtid()); + if (thd->is_error() && !wsrep_must_ignore_error(thd)) + { + wsrep_apply_error err; + err.store(thd); + client_state.leave_toi(); + } + else + { + ret= client_state.leave_toi(); + } + + if (ret == 0) + { + WSREP_DEBUG("TO END: %lld", client_state.toi_meta().seqno().get()); + } + else + { + WSREP_WARN("TO isolation end failed for: %d, schema: %s, sql: %s", + ret, (thd->db.str ? thd->db.str : "(null)"), WSREP_QUERY(thd)); + } } +} - ret = wsrep->resync(wsrep); - if (ret != WSREP_OK) +static int wsrep_RSU_begin(THD *thd, const char *db_, const char *table_) +{ + WSREP_DEBUG("RSU BEGIN: %lld, : %s", wsrep_thd_trx_seqno(thd), + WSREP_QUERY(thd)); + if (thd->wsrep_cs().begin_rsu(5000)) { - WSREP_WARN("resync failed %d for schema: %s, query: %s", ret, - thd->get_db(), thd->query()); - return; + WSREP_WARN("RSU begin failed"); + } + else + { + thd->variables.wsrep_on= 0; } + return 0; +} - thd->variables.wsrep_on = 1; +static void wsrep_RSU_end(THD *thd) +{ + WSREP_DEBUG("RSU END: %lld : %s", wsrep_thd_trx_seqno(thd), + WSREP_QUERY(thd)); + if (thd->wsrep_cs().end_rsu()) + { + WSREP_WARN("Failed to end RSU, server may need to be restarted"); + } + thd->variables.wsrep_on= 1; } int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, const TABLE_LIST* table_list, Alter_info* alter_info) { - int ret= 0; - /* No isolation for applier or replaying threads. */ - if (thd->wsrep_exec_mode == REPL_RECV) - return 0; + if (!wsrep_thd_is_local(thd)) return 0; + int ret= 0; mysql_mutex_lock(&thd->LOCK_thd_data); - if (thd->wsrep_conflict_state == MUST_ABORT) + if (thd->wsrep_trx().state() == wsrep::transaction::s_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()); @@ -1820,20 +1965,20 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, } mysql_mutex_unlock(&thd->LOCK_thd_data); - DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_STATE); - DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno == WSREP_SEQNO_UNDEFINED); + DBUG_ASSERT(wsrep_thd_is_local(thd)); + DBUG_ASSERT(thd->wsrep_trx().ws_meta().seqno().is_undefined()); - if (thd->has_read_only_protection()) + if (thd->global_read_lock.is_acquired()) { - WSREP_DEBUG("Aborting TOI: Global Read-Lock (FTWRL) in place: %s %lld", - thd->query(), (longlong) thd->thread_id); + WSREP_DEBUG("Aborting TOI: Global Read-Lock (FTWRL) in place: %s %llu", + 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_DEBUG("thread holds MDL locks at TI begin: %s %llu", + WSREP_QUERY(thd), thd->thread_id); } /* @@ -1845,11 +1990,11 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, */ if (wsrep_auto_increment_control) { - thd->variables.auto_increment_offset = 1; - thd->variables.auto_increment_increment = 1; + thd->variables.auto_increment_offset= 1; + thd->variables.auto_increment_increment= 1; } - if (thd->variables.wsrep_on && thd->wsrep_exec_mode==LOCAL_STATE) + if (thd->variables.wsrep_on && wsrep_thd_is_local(thd)) { switch (thd->variables.wsrep_OSU_method) { case WSREP_OSU_TOI: @@ -1865,48 +2010,53 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, break; } switch (ret) { - case 0: thd->wsrep_exec_mode= TOTAL_ORDER; break; + case 0: /* wsrep_TOI_begin sould set toi mode */ break; case 1: /* TOI replication skipped, treat as success */ - ret = 0; + ret= 0; break; case -1: /* TOI replication failed, treat as error */ break; } } + return ret; } void wsrep_to_isolation_end(THD *thd) { - if (thd->wsrep_exec_mode == TOTAL_ORDER) + DBUG_ASSERT(wsrep_thd_is_local_toi(thd) || + wsrep_thd_is_in_rsu(thd)); + if (wsrep_thd_is_local_toi(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; - default: - WSREP_WARN("Unsupported wsrep OSU method at isolation end: %lu", - thd->variables.wsrep_OSU_method); - break; - } - wsrep_cleanup_transaction(thd); + DBUG_ASSERT(thd->variables.wsrep_OSU_method == WSREP_OSU_TOI); + wsrep_TOI_end(thd); } + else if (wsrep_thd_is_in_rsu(thd)) + { + DBUG_ASSERT(thd->variables.wsrep_OSU_method == WSREP_OSU_RSU); + wsrep_RSU_end(thd); + } + else + { + DBUG_ASSERT(0); + } + if (wsrep_emulate_bin_log) wsrep_thd_binlog_trx_reset(thd); } #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: (%llu \tseqno %lld \twsrep (%s, %s, %s) cmd %d %d \t%s)\n" \ + "granted: (%llu \tseqno %lld \twsrep (%s, %s, %s) 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, \ + req->thread_id, (long long)wsrep_thd_trx_seqno(req), \ + wsrep_thd_client_mode_str(req), wsrep_thd_client_state_str(req), wsrep_thd_transaction_state_str(req), \ 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, \ + gra->thread_id, (long long)wsrep_thd_trx_seqno(gra), \ + wsrep_thd_client_mode_str(gra), wsrep_thd_client_state_str(gra), wsrep_thd_transaction_state_str(gra), \ gra->get_command(), gra->lex->sql_command, gra->query()); /** @@ -1919,58 +2069,47 @@ void wsrep_to_isolation_end(THD *thd) @retval FALSE Lock request cannot be granted */ -bool wsrep_grant_mdl_exception(MDL_context *requestor_ctx, +void wsrep_handle_mdl_conflict(MDL_context *requestor_ctx, MDL_ticket *ticket, const MDL_key *key) { /* Fallback to the non-wsrep behaviour */ - if (!WSREP_ON) return FALSE; + if (!WSREP_ON) return; THD *request_thd= requestor_ctx->get_thd(); THD *granted_thd= ticket->get_ctx()->get_thd(); - bool ret= false; const char* schema= key->db_name(); int schema_len= key->db_name_length(); mysql_mutex_lock(&request_thd->LOCK_thd_data); + if (wsrep_thd_is_toi(request_thd) || + wsrep_thd_is_applying(request_thd)) { - /* - We consider granting MDL exceptions only for appliers (BF THD) and ones - executing under TOI mode. - - Rules: - 1. If granted/owner THD is also an applier (BF THD) or one executing - under TOI mode, then we grant the requested lock to the requester - THD. - @return true - - 2. If granted/owner THD is executing a FLUSH command or already has an - explicit lock, then do not grant the requested lock to the requester - THD and it has to wait. - @return false - - 3. In all other cases the granted/owner THD is aborted and the requested - lock is not granted to the requester THD, thus it has to wait. - @return false - */ - if (request_thd->wsrep_exec_mode == TOTAL_ORDER || - 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); ticket->wsrep_report(wsrep_debug); mysql_mutex_lock(&granted_thd->LOCK_thd_data); - if (granted_thd->wsrep_exec_mode == TOTAL_ORDER || - granted_thd->wsrep_exec_mode == REPL_RECV) + if (wsrep_thd_is_toi(granted_thd) || + wsrep_thd_is_applying(granted_thd)) { - 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(granted_thd) && !wsrep_thd_is_SR(request_thd)) + { + WSREP_MDL_LOG(INFO, "MDL conflict, DDL vs SR", + schema, schema_len, request_thd, granted_thd); + mysql_mutex_unlock(&granted_thd->LOCK_thd_data); + wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); + } + 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_thd_data); + unireg_abort(1); + } } else if (granted_thd->lex->sql_command == SQLCOM_FLUSH || granted_thd->mdl_context.has_explicit_locks()) @@ -1978,173 +2117,57 @@ 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; + } + else if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE) + { + WSREP_DEBUG("DROP caused BF abort, conf %s", + wsrep_thd_transaction_state_str(granted_thd)); + ticket->wsrep_report(wsrep_debug); + mysql_mutex_unlock(&granted_thd->LOCK_thd_data); + wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); } 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_trx().active()) { - 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) + mysql_mutex_unlock(&granted_thd->LOCK_thd_data); + wsrep_abort_thd(request_thd, granted_thd, 1); + } + else + { + /* + Granted_thd is likely executing with wsrep_on=0. If the requesting + thd is BF, BF abort and wait. + */ + mysql_mutex_unlock(&granted_thd->LOCK_thd_data); + if (wsrep_thd_is_BF(request_thd, FALSE)) { - WSREP_DEBUG("MDL granted, but committing thd abort scheduled"); + ha_abort_transaction(request_thd, granted_thd, TRUE); } else { - WSREP_MDL_LOG(DEBUG, "MDL conflict-> BF abort", schema, schema_len, - request_thd, granted_thd); + WSREP_MDL_LOG(INFO, "MDL unknown BF-BF conflict", schema, schema_len, + request_thd, granted_thd); + ticket->wsrep_report(true); + unireg_abort(1); } - ticket->wsrep_report(true); } - - 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; -} - - -pthread_handler_t start_wsrep_THD(void *arg) -{ - THD *thd; - wsrep_thd_processor_fun processor= (wsrep_thd_processor_fun)arg; - - if (my_thread_init() || (!(thd= new THD(next_thread_id(), true)))) - { - goto error; - } - - mysql_mutex_lock(&LOCK_thread_count); - - if (wsrep_gtid_mode) - { - /* Adjust domain_id. */ - thd->variables.gtid_domain_id= wsrep_gtid_domain_id; - } - - thd->real_id=pthread_self(); // Keep purify happy - thread_created++; - threads.append(thd); - - my_net_init(&thd->net,(st_vio*) 0, thd, MYF(0)); - - DBUG_PRINT("wsrep",(("creating thread %lld"), (long long)thd->thread_id)); - thd->prior_thr_create_utime= thd->start_utime= microsecond_interval_timer(); - (void) mysql_mutex_unlock(&LOCK_thread_count); - - /* from bootstrap()... */ - thd->bootstrap=1; - thd->max_client_packet_length= thd->net.max_packet; - thd->security_ctx->master_access= ~(ulong)0; - - /* from handle_one_connection... */ - pthread_detach_this_thread(); - - mysql_thread_set_psi_id(thd->thread_id); - thd->thr_create_utime= microsecond_interval_timer(); - if (MYSQL_CALLBACK_ELSE(thread_scheduler, init_new_connection_thread, (), 0)) - { - close_connection(thd, ER_OUT_OF_RESOURCES); - statistic_increment(aborted_connects,&LOCK_status); - MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); - goto error; - } - -// </5.1.17> - /* - handle_one_connection() is normally the only way a thread would - start and would always be on the very high end of the stack , - therefore, the thread stack always starts at the address of the - first local variable of handle_one_connection, which is thd. We - need to know the start of the stack so that we could check for - stack overruns. - */ - DBUG_PRINT("wsrep", ("handle_one_connection called by thread %lld\n", - (long long)thd->thread_id)); - /* now that we've called my_thread_init(), it is safe to call DBUG_* */ - - thd->thread_stack= (char*) &thd; - if (thd->store_globals()) - { - close_connection(thd, ER_OUT_OF_RESOURCES); - statistic_increment(aborted_connects,&LOCK_status); - MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); - goto error; - } - - thd->system_thread= SYSTEM_THREAD_SLAVE_SQL; - thd->security_ctx->skip_grants(); - - /* handle_one_connection() again... */ - //thd->version= refresh_version; - thd->proc_info= 0; - thd->set_command(COM_SLEEP); - thd->init_for_queries(); - - mysql_mutex_lock(&LOCK_thread_count); - wsrep_running_threads++; - mysql_cond_broadcast(&COND_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); - - processor(thd); - - close_connection(thd, 0); - - mysql_mutex_lock(&LOCK_thread_count); - wsrep_running_threads--; - WSREP_DEBUG("wsrep running threads now: %lu", wsrep_running_threads); - mysql_cond_broadcast(&COND_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); - - // Note: We can't call THD destructor without crashing - // if plugins have not been initialized. However, in most of the - // cases this means that pre SE initialization SST failed and - // we are going to exit anyway. - if (plugins_are_initialized) - { - net_end(&thd->net); - MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 1)); - } - else - { - // TODO: lightweight cleanup to get rid of: - // 'Error in my_thread_global_end(): 2 threads didn't exit' - // at server shutdown - } - - unlink_not_visible_thd(thd); - delete thd; - my_thread_end(); - return(NULL); - -error: - WSREP_ERROR("Failed to create/initialize system thread"); - - /* Abort if its the first applier/rollbacker thread. */ - if (!mysqld_server_initialized) - unireg_abort(1); - else - return NULL; } - /**/ static bool abort_replicated(THD *thd) { bool ret_code= false; - if (thd->wsrep_query_state== QUERY_COMMITTING) + if (thd->wsrep_trx().state() == wsrep::transaction::s_committing) { WSREP_DEBUG("aborting replicated trx: %llu", (ulonglong)(thd->real_id)); @@ -2154,38 +2177,34 @@ static bool abort_replicated(THD *thd) return ret_code; } - /**/ static inline bool is_client_connection(THD *thd) { return (thd->wsrep_client_thread && thd->variables.wsrep_on); } - 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_trx().state() == wsrep::transaction::s_replaying) ? true : false; mysql_mutex_unlock(&thd->LOCK_thd_data); return ret; } - 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_trx().state() == wsrep::transaction::s_committing) ? true : false; mysql_mutex_unlock(&thd->LOCK_thd_data); return ret; } - static bool have_client_connections() { THD *tmp; @@ -2222,7 +2241,6 @@ static void wsrep_close_thread(THD *thd) } } - static my_bool have_committing_connections() { THD *tmp; @@ -2236,6 +2254,7 @@ static my_bool have_committing_connections() if (is_committing_connection(tmp)) { + mysql_mutex_unlock(&LOCK_thread_count); return TRUE; } } @@ -2243,7 +2262,6 @@ static my_bool have_committing_connections() return FALSE; } - int wsrep_wait_committing_connections_close(int wait_time) { int sleep_time= 100; @@ -2261,8 +2279,7 @@ int wsrep_wait_committing_connections_close(int wait_time) return 0; } - -void wsrep_close_client_connections(my_bool wait_to_end, THD *except_caller_thd) +void wsrep_close_client_connections(my_bool wait_to_end, THD* except_caller_thd) { /* First signal all threads that it's time to die @@ -2305,12 +2322,7 @@ void wsrep_close_client_connections(my_bool wait_to_end, THD *except_caller_thd) /* instead of wsrep_close_thread() we do now soft kill by THD::awake */ - mysql_mutex_lock(&tmp->LOCK_thd_data); - tmp->awake(KILL_CONNECTION); - - mysql_mutex_unlock(&tmp->LOCK_thd_data); - } mysql_mutex_unlock(&LOCK_thread_count); @@ -2360,7 +2372,6 @@ void wsrep_close_applier(THD *thd) wsrep_close_thread(thd); } - void wsrep_close_threads(THD *thd) { THD *tmp; @@ -2386,10 +2397,12 @@ 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) - // 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. + while (wsrep_running_threads > 2) + /* + 2 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. + */ { if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION) { @@ -2425,7 +2438,6 @@ void wsrep_wait_appliers_close(THD *thd) */ } - void wsrep_kill_mysql(THD *thd) { if (mysqld_server_started) @@ -2442,267 +2454,167 @@ void wsrep_kill_mysql(THD *thd) } } - -static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len) +void +wsrep_last_committed_id(wsrep_gtid_t* gtid) { - String log_query; - sp_head *sp = thd->lex->sphead; - sql_mode_t saved_mode= thd->variables.sql_mode; - String retstr(64); - LEX_CSTRING returns= empty_clex_str; - retstr.set_charset(system_charset_info); - - log_query.set_charset(system_charset_info); - - if (sp->m_handler->type() == TYPE_ENUM_FUNCTION) - { - sp_returns_type(thd, retstr, sp); - returns= retstr.lex_cstring(); - } - if (sp->m_handler-> - show_create_sp(thd, &log_query, - sp->m_explicit_name ? sp->m_db : null_clex_str, - sp->m_name, sp->m_params, returns, - sp->m_body, sp->chistics(), - thd->lex->definer[0], - thd->lex->create_info, - saved_mode)) - { - WSREP_WARN("SP create string failed: schema: %s, query: %s", - thd->get_db(), thd->query()); - return 1; - } - - return wsrep_to_buf_helper(thd, log_query.ptr(), log_query.length(), buf, buf_len); + wsrep::gtid ret= Wsrep_server_state::instance().last_committed_gtid(); + memcpy(gtid->uuid.data, ret.id().data(), sizeof(gtid->uuid.data)); + gtid->seqno= ret.seqno().get(); } - -extern int wsrep_on(THD *thd) +void +wsrep_node_uuid(wsrep_uuid_t& uuid) { - return (int)(WSREP(thd)); + uuid= node_uuid; } - -extern "C" bool wsrep_thd_is_wsrep_on(THD *thd) +int wsrep_must_ignore_error(THD* thd) { - return thd->variables.wsrep_on; -} + const int error= thd->get_stmt_da()->sql_errno(); + const uint flags= sql_command_flags[thd->lex->sql_command]; + DBUG_ASSERT(error); + DBUG_ASSERT((wsrep_thd_is_toi(thd)) || + (wsrep_thd_is_applying(thd) && thd->wsrep_apply_toi)); -bool wsrep_consistency_check(THD *thd) -{ - return thd->wsrep_consistency_check == CONSISTENCY_CHECK_RUNNING; -} - - -extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode) -{ - thd->wsrep_exec_mode= mode; -} + 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; + } + } -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; -} - - -enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd) -{ - return thd->wsrep_exec_mode; -} - - -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"; -} - - -enum wsrep_query_state wsrep_thd_query_state(THD *thd) -{ - 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"; -} - - -enum wsrep_conflict_state wsrep_thd_get_conflict_state(THD *thd) -{ - 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"; -} - - -wsrep_ws_handle_t* wsrep_thd_ws_handle(THD *thd) -{ - return &thd->wsrep_ws_handle; -} - - -void wsrep_thd_LOCK(THD *thd) -{ - mysql_mutex_lock(&thd->LOCK_thd_data); -} - + return 0; -void wsrep_thd_UNLOCK(THD *thd) -{ - mysql_mutex_unlock(&thd->LOCK_thd_data); +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; } - -extern "C" time_t wsrep_thd_query_start(THD *thd) +int wsrep_ignored_error_code(Log_event* ev, int error) { - return thd->query_start(); -} + const THD* thd= ev->thd; + DBUG_ASSERT(error); + DBUG_ASSERT(wsrep_thd_is_applying(thd) && + !wsrep_thd_is_local_toi(thd)); -extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd) -{ - return thd->wsrep_rand; -} - -longlong wsrep_thd_trx_seqno(THD *thd) -{ - return (thd) ? thd->wsrep_trx_meta.gtid.seqno : WSREP_SEQNO_UNDEFINED; -} + 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 || ev_type == DELETE_ROWS_EVENT_V1) + && error == ER_KEY_NOT_FOUND) + goto ignore_error; + } + return 0; -extern "C" query_id_t wsrep_thd_query_id(THD *thd) -{ - return thd->query_id; +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; } - -char *wsrep_thd_query(THD *thd) +bool wsrep_provider_is_SR_capable() { - return (thd) ? thd->query() : NULL; + return Wsrep_server_state::has_capability(wsrep::provider::capability::streaming); } -extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd) +int wsrep_ordered_commit_if_no_binlog(THD* thd, bool all) { - return thd->wsrep_last_query_id; + if (((wsrep_thd_is_local(thd) && + (WSREP_EMULATE_BINLOG(thd) || !thd->variables.sql_log_bin)) || + (wsrep_thd_is_applying(thd) && !opt_log_slave_updates)) + && wsrep_thd_trx_seqno(thd) > 0) + { + wsrep_apply_error unused; + return wsrep_ordered_commit(thd, all, unused); + } + return 0; } - -extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id) +wsrep_status_t wsrep_tc_log_commit(THD* thd) { - thd->wsrep_last_query_id= id; -} - + int cookie; + my_xid xid= thd->transaction.xid_state.xid.get_my_xid(); -extern "C" void wsrep_thd_awake(THD *thd, my_bool signal) -{ - if (signal) + DBUG_ASSERT(thd->lex->sql_command == SQLCOM_LOAD); + if (wsrep_before_commit(thd, true)) { - thd->awake(KILL_QUERY); + WSREP_DEBUG("wsrep_tc_log_commit: wsrep_before_commit failed %llu", + thd->thread_id); + return WSREP_TRX_FAIL; } - else + cookie= tc_log->log_and_order(thd, xid, 1, false, true); + if (wsrep_after_commit(thd, true)) { - mysql_mutex_lock(&LOCK_wsrep_replaying); - mysql_cond_broadcast(&COND_wsrep_replaying); - mysql_mutex_unlock(&LOCK_wsrep_replaying); + WSREP_DEBUG("wsrep_tc_log_commit: wsrep_after_commit failed %llu", + thd->thread_id); + return WSREP_TRX_FAIL; + } + if (!cookie) + { + WSREP_DEBUG("log_and_order has failed %llu %d", thd->thread_id, cookie); + return WSREP_TRX_FAIL; + } + if (tc_log->unlog(cookie, xid)) + { + WSREP_DEBUG("log_and_order has failed %llu %d", thd->thread_id, cookie); + return WSREP_TRX_FAIL; } -} - - -int wsrep_thd_retry_counter(THD *thd) -{ - return(thd->wsrep_retry_counter); -} - - -extern "C" bool wsrep_thd_ignore_table(THD *thd) -{ - return thd->wsrep_ignore_table; -} - -extern int -wsrep_trx_order_before(THD *thd1, THD *thd2) -{ - if (wsrep_thd_trx_seqno(thd1) < wsrep_thd_trx_seqno(thd2)) { - WSREP_DEBUG("BF conflict, order: %lld %lld\n", - (long long)wsrep_thd_trx_seqno(thd1), - (long long)wsrep_thd_trx_seqno(thd2)); - return 1; + if (wsrep_after_statement(thd)) + { + return WSREP_TRX_FAIL; + } + /* 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); } - WSREP_DEBUG("waiting for BF, trx order: %lld %lld\n", - (long long)wsrep_thd_trx_seqno(thd1), - (long long)wsrep_thd_trx_seqno(thd2)); - return 0; + DBUG_ASSERT(thd->wsrep_next_trx_id() != WSREP_UNDEFINED_TRX_ID); + } + if (wsrep_start_transaction(thd, thd->wsrep_next_trx_id())) + { + return WSREP_TRX_FAIL; + } + DBUG_ASSERT(thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID); + return WSREP_OK; } - -int wsrep_trx_is_aborting(THD *thd_ptr) +int wsrep_thd_retry_counter(const THD *thd) { - if (thd_ptr) { - if ((((THD *)thd_ptr)->wsrep_conflict_state == MUST_ABORT) || - (((THD *)thd_ptr)->wsrep_conflict_state == ABORTING)) { - return 1; - } - } - return 0; + return thd->wsrep_retry_counter; } - -void wsrep_copy_query(THD *thd) +extern bool wsrep_thd_ignore_table(THD *thd) { - thd->wsrep_retry_command = thd->get_command(); - thd->wsrep_retry_query_len = thd->query_length(); - if (thd->wsrep_retry_query) { - my_free(thd->wsrep_retry_query); - } - thd->wsrep_retry_query = (char *)my_malloc( - thd->wsrep_retry_query_len + 1, MYF(0)); - strncpy(thd->wsrep_retry_query, thd->query(), thd->wsrep_retry_query_len); - thd->wsrep_retry_query[thd->wsrep_retry_query_len] = '\0'; + return thd->wsrep_ignore_table; } - bool wsrep_is_show_query(enum enum_sql_command command) { DBUG_ASSERT(command >= 0 && command <= SQLCOM_END); return (sql_command_flags[command] & CF_STATUS_COMMAND) != 0; } - bool wsrep_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, HA_CREATE_INFO *create_info) @@ -2753,8 +2665,7 @@ wsrep_error_label: #endif } - -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; @@ -2809,88 +2720,165 @@ static int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len) buf, buf_len); } -/***** callbacks for wsrep service ************/ - -my_bool get_wsrep_debug() +void* start_wsrep_THD(void *arg) { - return wsrep_debug; -} + THD *thd; -my_bool get_wsrep_load_data_splitting() -{ - return wsrep_load_data_splitting; -} + Wsrep_thd_args* thd_args= (Wsrep_thd_args*) arg; -long get_wsrep_protocol_version() -{ - return wsrep_protocol_version; -} + if (my_thread_init() || (!(thd= new THD(next_thread_id(), true)))) + { + goto error; + } -my_bool get_wsrep_drupal_282555_workaround() -{ - return wsrep_drupal_282555_workaround; -} + mysql_mutex_lock(&LOCK_thread_count); -my_bool get_wsrep_recovery() -{ - return wsrep_recovery; -} + if (wsrep_gtid_mode) + { + /* Adjust domain_id. */ + thd->variables.gtid_domain_id= wsrep_gtid_domain_id; + } -my_bool get_wsrep_log_conflicts() -{ - return wsrep_log_conflicts; -} + thd->real_id=pthread_self(); // Keep purify happy + thread_created++; + threads.append(thd); -wsrep_t *get_wsrep() -{ - return wsrep; -} + my_net_init(&thd->net,(st_vio*) 0, thd, MYF(0)); -my_bool get_wsrep_certify_nonPK() -{ - return wsrep_certify_nonPK; -} + DBUG_PRINT("wsrep",(("creating thread %lld"), (long long)thd->thread_id)); + thd->prior_thr_create_utime= thd->start_utime= microsecond_interval_timer(); + (void) mysql_mutex_unlock(&LOCK_thread_count); -void wsrep_lock_rollback() -{ - mysql_mutex_lock(&LOCK_wsrep_rollback); -} + /* from bootstrap()... */ + thd->bootstrap=1; + thd->max_client_packet_length= thd->net.max_packet; + thd->security_ctx->master_access= ~(ulong)0; -void wsrep_unlock_rollback() -{ - mysql_cond_signal(&COND_wsrep_rollback); - mysql_mutex_unlock(&LOCK_wsrep_rollback); -} + /* from handle_one_connection... */ + pthread_detach_this_thread(); -my_bool wsrep_aborting_thd_contains(THD *thd) -{ - mysql_mutex_assert_owner(&LOCK_wsrep_rollback); - wsrep_aborting_thd_t abortees = wsrep_aborting_thd; - while (abortees) + mysql_thread_set_psi_id(thd->thread_id); + thd->thr_create_utime= microsecond_interval_timer(); + if (MYSQL_CALLBACK_ELSE(thread_scheduler, init_new_connection_thread, (), 0)) { - if (abortees->aborting_thd == thd) - return true; - abortees = abortees->next; + close_connection(thd, ER_OUT_OF_RESOURCES); + statistic_increment(aborted_connects,&LOCK_status); + MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); + goto error; } - return false; + +// </5.1.17> + /* + handle_one_connection() is normally the only way a thread would + start and would always be on the very high end of the stack , + therefore, the thread stack always starts at the address of the + first local variable of handle_one_connection, which is thd. We + need to know the start of the stack so that we could check for + stack overruns. + */ + DBUG_PRINT("wsrep", ("handle_one_connection called by thread %lld\n", + (long long)thd->thread_id)); + /* now that we've called my_thread_init(), it is safe to call DBUG_* */ + + thd->thread_stack= (char*) &thd; + if (thd->store_globals()) + { + 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; + } + + thd->system_thread= SYSTEM_THREAD_SLAVE_SQL; + thd->security_ctx->skip_grants(); + + /* handle_one_connection() again... */ + thd->proc_info= 0; + thd->set_command(COM_SLEEP); + thd->init_for_queries(); + mysql_mutex_lock(&LOCK_thread_count); + wsrep_running_threads++; + mysql_cond_broadcast(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); + + WSREP_DEBUG("wsrep system thread %llu, %p starting", + thd->thread_id, thd); + thd_args->fun()(thd, thd_args->args()); + + WSREP_DEBUG("wsrep system thread: %llu, %p closing", + thd->thread_id, thd); + + /* Wsrep may reset globals during thread context switches, store globals + before cleanup. */ + thd->store_globals(); + + 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); + mysql_cond_broadcast(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); + /* + Note: We can't call THD destructor without crashing + if plugins have not been initialized. However, in most of the + cases this means that pre SE initialization SST failed and + we are going to exit anyway. + */ + if (plugins_are_initialized) + { + net_end(&thd->net); + MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 1)); + } + else + { + /* + TODO: lightweight cleanup to get rid of: + 'Error in my_thread_global_end(): 2 threads didn't exit' + at server shutdown + */ + } + + unlink_not_visible_thd(thd); + delete thd; + my_thread_end(); + return(NULL); + +error: + WSREP_ERROR("Failed to create/initialize system thread"); + + /* Abort if its the first applier/rollbacker thread. */ + if (!mysqld_server_initialized) + unireg_abort(1); + else + return NULL; } -void wsrep_aborting_thd_enqueue(THD *thd) +enum wsrep::streaming_context::fragment_unit wsrep_fragment_unit(ulong unit) { - 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; + switch (unit) + { + case WSREP_FRAG_BYTES: return wsrep::streaming_context::bytes; + case WSREP_FRAG_ROWS: return wsrep::streaming_context::row; + case WSREP_FRAG_STATEMENTS: return wsrep::streaming_context::statement; + default: + DBUG_ASSERT(0); + return wsrep::streaming_context::bytes; + } } -bool wsrep_node_is_donor() +/***** callbacks for wsrep service ************/ + +my_bool get_wsrep_recovery() { - return (WSREP_ON) ? (wsrep_config_state->get_status() == 2) : false; + return wsrep_recovery; } -bool wsrep_node_is_synced() +bool wsrep_consistency_check(THD *thd) { - return (WSREP_ON) ? (wsrep_config_state->get_status() == 4) : false; + return thd->wsrep_consistency_check == CONSISTENCY_CHECK_RUNNING; } diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index b434c248347..957f1ef3ab1 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 @@ -13,24 +13,32 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#include <wsrep.h> - #ifndef WSREP_MYSQLD_H #define WSREP_MYSQLD_H -#include <mysql/plugin.h> -#include <mysql/service_wsrep.h> +#include <wsrep.h> #ifdef WITH_WSREP +#include <mysql/plugin.h> +#include "mysql/service_wsrep.h" + +#include <my_global.h> +#include <my_pthread.h> +#include "log.h" +#include "mysqld.h" + 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 "wsrep/provider.hpp" +#include "wsrep/streaming_context.hpp" +#include "wsrep_api.h" +#include <vector> +#include "wsrep_server_state.h" + #define WSREP_UNDEFINED_TRX_ID ULONGLONG_MAX class set_var; @@ -42,20 +50,7 @@ enum wsrep_consistency_check_mode { 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; // MySQL wsrep options extern const char* wsrep_provider; @@ -69,24 +64,33 @@ extern const char* wsrep_data_home_dir; extern const char* wsrep_dbug_option; extern long wsrep_slave_threads; extern int wsrep_slave_count_change; +extern MYSQL_PLUGIN_IMPORT my_bool wsrep_debug; extern my_bool wsrep_convert_LOCK_to_trx; extern ulong wsrep_retry_autocommit; extern my_bool wsrep_auto_increment_control; +extern my_bool wsrep_drupal_282555_workaround; extern my_bool wsrep_incremental_data_collection; 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 my_bool wsrep_certify_nonPK; +extern long int wsrep_protocol_version; extern ulong wsrep_forced_binlog_format; extern my_bool wsrep_desync; extern ulong wsrep_reject_queries; +extern my_bool wsrep_recovery; extern my_bool wsrep_replicate_myisam; +extern my_bool wsrep_log_conflicts; extern ulong wsrep_mysql_replication_bundle; +extern my_bool wsrep_load_data_splitting; 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_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; @@ -105,15 +109,34 @@ enum enum_wsrep_OSU_method { }; enum enum_wsrep_sync_wait { - WSREP_SYNC_WAIT_NONE = 0x0, + WSREP_SYNC_WAIT_NONE= 0x0, // select, begin - WSREP_SYNC_WAIT_BEFORE_READ = 0x1, - WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE = 0x2, - WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE = 0x4, - WSREP_SYNC_WAIT_BEFORE_SHOW = 0x8, - WSREP_SYNC_WAIT_MAX = 0xF + WSREP_SYNC_WAIT_BEFORE_READ= 0x1, + WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE= 0x2, + WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE= 0x4, + WSREP_SYNC_WAIT_BEFORE_SHOW= 0x8, + 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 }; +// Streaming Replication +#define WSREP_FRAG_BYTES 0 +#define WSREP_FRAG_ROWS 1 +#define WSREP_FRAG_STATEMENTS 2 + +#define WSREP_SR_STORE_NONE 0 +#define WSREP_SR_STORE_TABLE 1 + +extern const char *wsrep_fragment_units[]; +extern const char *wsrep_SR_store_types[]; + // MySQL status variables extern my_bool wsrep_connected; extern my_bool wsrep_ready; @@ -126,9 +149,18 @@ 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); +int wsrep_show_ready(THD *thd, SHOW_VAR *var, char *buff); +void wsrep_free_status(THD *thd); +void wsrep_update_cluster_state_uuid(const char* str); + +/* Filters out --wsrep-new-cluster oprtion from argv[] + * should be called in the very beginning of main() */ +void wsrep_filter_new_cluster (int* argc, char* argv[]); -int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope); int wsrep_init(); void wsrep_deinit(bool free_options); @@ -144,19 +176,17 @@ bool wsrep_before_SE(); // initialize wsrep before storage * @param before wsrep_before_SE() value */ void wsrep_init_startup(bool before); +/* Recover streaming transactions from fragment storage */ +void wsrep_recover_sr_from_storage(THD *); + // 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 void wsrep_close_client_connections(my_bool wait_to_end, + THD *except_caller_thd= NULL); 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); @@ -166,60 +196,87 @@ 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 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 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 enum wsrep::provider::status +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; - #define WSREP_ON \ - (global_system_variables.wsrep_on) - -#define WSREP_ON_NEW \ ((global_system_variables.wsrep_on) && \ wsrep_provider && \ strcmp(wsrep_provider, WSREP_NONE)) -#define WSREP(thd) \ +/* 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 && thd->variables.wsrep_on) +#define WSREP(thd) \ + (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) -#define WSREP_FORMAT(my_format) \ - ((wsrep_forced_binlog_format != BINLOG_FORMAT_UNSPEC) \ - ? wsrep_forced_binlog_format : (ulong)(my_format)) +#define WSREP_BINLOG_FORMAT(my_format) \ + ((wsrep_forced_binlog_format != BINLOG_FORMAT_UNSPEC) ? \ + wsrep_forced_binlog_format : my_format) // prefix all messages with "WSREP" -void wsrep_log(void (*fun)(const char *, ...), const char *format, ...); -#define WSREP_LOG(fun, ...) wsrep_log(fun, ## __VA_ARGS__) -#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 " \ - " SQL: %s", \ - role, thd_get_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) \ - ); - -#define WSREP_LOG_CONFLICT(bf_thd, victim_thd, bf_abort) \ - if (wsrep_debug || wsrep_log_conflicts) \ - { \ - WSREP_LOG(sql_print_information, "cluster conflict due to %s for threads:",\ - (bf_abort) ? "high priority abort" : "certification failure" \ - ); \ - if (bf_thd != NULL) WSREP_LOG_CONFLICT_THD(bf_thd, "Winning thread"); \ - if (victim_thd) WSREP_LOG_CONFLICT_THD(victim_thd, "Victim thread"); \ +#define WSREP_LOG(fun, ...) \ + do { \ + char msg[1024]= {'\0'}; \ + snprintf(msg, sizeof(msg) - 1, ## __VA_ARGS__); \ + fun("WSREP: %s", msg); \ + } while(0) + +#define WSREP_DEBUG(...) \ + if (wsrep_debug) WSREP_LOG(sql_print_information, ##__VA_ARGS__) +#define WSREP_INFO(...) WSREP_LOG(sql_print_information, ##__VA_ARGS__) +#define WSREP_WARN(...) WSREP_LOG(sql_print_warning, ##__VA_ARGS__) +#define WSREP_ERROR(...) WSREP_LOG(sql_print_error, ##__VA_ARGS__) + +#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 " \ + " SQL: %s", \ + role, \ + thd_get_thread_id(thd), \ + wsrep_thd_client_mode_str(thd), \ + wsrep_thd_client_state_str(thd), \ + wsrep_thd_transaction_state_str(thd), \ + wsrep_thd_trx_seqno(thd), \ + wsrep_thd_query(thd) \ + ); + +#define WSREP_LOG_CONFLICT(bf_thd, victim_thd, bf_abort) \ + if (wsrep_debug || wsrep_log_conflicts) \ + { \ + WSREP_LOG(sql_print_information, "cluster conflict due to %s for threads:", \ + (bf_abort) ? "high priority abort" : "certification failure" \ + ); \ + if (bf_thd) 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 \ @@ -232,15 +289,6 @@ extern void wsrep_ready_wait(); class Ha_trx_info; struct THD_TRANS; -void wsrep_register_hton(THD* thd, bool all); -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; @@ -248,24 +296,26 @@ 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 extern rpl_sidno wsrep_sidno; #endif /* GTID_SUPPORT */ extern my_bool wsrep_preordered_opt; -extern handlerton *wsrep_hton; #ifdef HAVE_PSI_INTERFACE + +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; @@ -274,12 +324,16 @@ 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_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 */ @@ -287,42 +341,33 @@ struct TABLE_LIST; class Alter_info; int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, const TABLE_LIST* table_list, - Alter_info* alter_info = NULL); + Alter_info* alter_info= NULL); + 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_trigger_query(THD *thd, uchar** buf, size_t* buf_len); int wsrep_create_event_query(THD *thd, uchar** buf, size_t* buf_len); -extern bool -wsrep_grant_mdl_exception(MDL_context *requestor_ctx, - MDL_ticket *ticket, - const MDL_key *key); -IO_CACHE * get_trans_log(THD * thd); -bool wsrep_trans_cache_is_empty(THD *thd); -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); +bool wsrep_stmt_rollback_is_safe(THD* thd); -typedef void (*wsrep_thd_processor_fun)(THD *); -pthread_handler_t start_wsrep_THD(void *arg); -int wsrep_wait_committing_connections_close(int wait_time); -extern void wsrep_close_client_connections(my_bool wait_to_end, - THD *except_caller_thd = NULL); -void wsrep_close_applier(THD *thd); -void wsrep_close_applier_threads(int count); -void wsrep_wait_appliers_close(THD *thd); -void wsrep_kill_mysql(THD *thd); -void wsrep_close_threads(THD *thd); -void wsrep_copy_query(THD *thd); -bool wsrep_is_show_query(enum enum_sql_command command); -void wsrep_replay_transaction(THD *thd); -bool wsrep_create_like_table(THD* thd, TABLE_LIST* table, - TABLE_LIST* src_table, - HA_CREATE_INFO *create_info); +void wsrep_init_sidno(const wsrep_uuid_t&); bool wsrep_node_is_donor(); bool wsrep_node_is_synced(); +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); + typedef struct wsrep_key_arr { wsrep_key_t* keys; @@ -335,38 +380,125 @@ bool wsrep_prepare_keys_for_isolation(THD* thd, 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) +extern void +wsrep_handle_mdl_conflict(MDL_context *requestor_ctx, + MDL_ticket *ticket, + const MDL_key *key); +IO_CACHE * get_trans_log(THD * thd); +bool wsrep_trans_cache_is_empty(THD *thd); +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*, 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_; } -#else /* WITH_WSREP */ + 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*); + +void wsrep_close_threads(THD *thd); +bool wsrep_is_show_query(enum enum_sql_command command); +void wsrep_replay_transaction(THD *thd); +bool wsrep_create_like_table(THD* thd, TABLE_LIST* table, + TABLE_LIST* src_table, + HA_CREATE_INFO *create_info); +bool wsrep_node_is_donor(); +bool wsrep_node_is_synced(); + +/** + * 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*, bool); + +/** + * 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); + +/** + * Initialize WSREP server instance. + * + * @return Zero on success, non-zero on error. + */ +int wsrep_init_server(); + +/** + * Initialize WSREP globals. This should be done after server initialization + * is complete and the server has joined to the cluster. + * + */ +void wsrep_init_globals(); + +/** + * Deinit and release WSREP resources. + */ +void wsrep_deinit_server(); + +/** + * Convert streaming fragment unit (WSREP_FRAG_BYTES, WSREP_FRAG_ROWS...) + * to corresponding wsrep-lib fragment_unit + */ +enum wsrep::streaming_context::fragment_unit wsrep_fragment_unit(ulong unit); + +#else /* !WITH_WSREP */ + +/* These macros are needed to compile MariaDB without WSREP support + * (e.g. embedded) */ #define WSREP(T) (0) #define WSREP_ON (0) #define WSREP_EMULATE_BINLOG(thd) (0) -#define WSREP_CLIENT(thd) (0) -#define WSREP_FORMAT(my_format) ((ulong)my_format) +#define WSREP_EMULATE_BINLOG_NNULL(thd) (0) +#define WSREP_BINLOG_FORMAT(my_format) ((ulong)my_format) #define WSREP_PROVIDER_EXISTS (0) #define wsrep_emulate_bin_log (0) #define wsrep_to_isolation (0) -#define wsrep_init() (1) -#define wsrep_prepend_PATH(X) #define wsrep_before_SE() (0) #define wsrep_init_startup(X) -#define wsrep_must_sync_wait(...) (0) -#define wsrep_sync_wait(...) (0) -#define wsrep_to_isolation_begin(...) (0) -#define wsrep_register_hton(...) do { } while(0) #define wsrep_check_opts() (0) -#define wsrep_stop_replication(X) do { } while(0) -#define wsrep_inited (0) -#define wsrep_deinit(X) do { } while(0) -#define wsrep_recover() do { } while(0) -#define wsrep_slave_threads (1) -#define wsrep_replicate_myisam (0) #define wsrep_thr_init() do {} while(0) #define wsrep_thr_deinit() do {} while(0) -#define wsrep_running_threads (0) -#define WSREP_BINLOG_FORMAT(my_format) my_format +#define wsrep_init_globals() do {} while(0) +#define wsrep_create_appliers(X) do {} while(0) + #endif /* WITH_WSREP */ + #endif /* WSREP_MYSQLD_H */ diff --git a/sql/wsrep_notify.cc b/sql/wsrep_notify.cc index 92bcc8eda43..ad94aecb6b4 100644 --- a/sql/wsrep_notify.cc +++ b/sql/wsrep_notify.cc @@ -18,22 +18,8 @@ #include "wsrep_priv.h" #include "wsrep_utils.h" - -static const char* _status_str(wsrep_member_status_t status) -{ - switch (status) - { - case WSREP_MEMBER_UNDEFINED: return "Undefined"; - case WSREP_MEMBER_JOINER: return "Joiner"; - case WSREP_MEMBER_DONOR: return "Donor"; - case WSREP_MEMBER_JOINED: return "Joined"; - case WSREP_MEMBER_SYNCED: return "Synced"; - default: return "Error(?)"; - } -} - -void wsrep_notify_status (wsrep_member_status_t status, - const wsrep_view_info_t* view) +void wsrep_notify_status(enum wsrep::server_state::state status, + const wsrep::view* view) { if (!wsrep_notify_cmd || 0 == strlen(wsrep_notify_cmd)) { @@ -42,51 +28,44 @@ void wsrep_notify_status (wsrep_member_status_t status, } char cmd_buf[1 << 16]; // this can be long - long cmd_len = sizeof(cmd_buf) - 1; - char* cmd_ptr = cmd_buf; - long cmd_off = 0; + long cmd_len= sizeof(cmd_buf) - 1; + char* cmd_ptr= cmd_buf; + long cmd_off= 0; cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, "%s", wsrep_notify_cmd); - if (status >= WSREP_MEMBER_UNDEFINED && status < WSREP_MEMBER_ERROR) - { - cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, " --status %s", - _status_str(status)); - } - else - { - /* here we preserve provider error codes */ - cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, - " --status 'Error(%d)'", status); - } + cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, " --status %s", + to_c_string(status)); - if (0 != view) + if (view != NULL) { - char uuid_str[40]; - - wsrep_uuid_print (&view->state_id.uuid, uuid_str, sizeof(uuid_str)); + std::ostringstream uuid; + uuid << view->state_id().id(); cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, - " --uuid %s", uuid_str); + " --uuid %s", uuid.str().c_str()); cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, - " --primary %s", view->view >= 0 ? "yes" : "no"); + " --primary %s", view->view_seqno().get() >= 0 ? "yes" : "no"); cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, - " --index %d", view->my_idx); + " --index %ld", view->own_index()); - if (view->memb_num) + const std::vector<wsrep::view::member>& members(view->members()); + if (members.size()) { - cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, " --members"); - - for (int i = 0; i < view->memb_num; i++) - { - wsrep_uuid_print (&view->members[i].id, uuid_str, sizeof(uuid_str)); - cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, - "%c%s/%s/%s", i > 0 ? ',' : ' ', - uuid_str, view->members[i].name, - view->members[i].incoming); - } + cmd_off += snprintf (cmd_ptr + cmd_off, cmd_len - cmd_off, " --members"); + + for (unsigned int i= 0; i < members.size(); i++) + { + std::ostringstream id; + id << members[i].id(); + cmd_off += snprintf(cmd_ptr + cmd_off, cmd_len - cmd_off, + "%c%s/%s/%s", i > 0 ? ',' : ' ', + id.str().c_str(), + members[i].name().c_str(), + members[i].incoming().c_str()); + } } } @@ -100,7 +79,7 @@ void wsrep_notify_status (wsrep_member_status_t status, wsp::process p(cmd_ptr, "r", NULL); p.wait(); - int err = p.error(); + int err= p.error(); if (err) { diff --git a/sql/wsrep_plugin.cc b/sql/wsrep_plugin.cc new file mode 100644 index 00000000000..83618a50637 --- /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 0; +} + +static int wsrep_plugin_deinit(void *p) +{ + WSREP_INFO("wsrep_plugin_deinit()"); + return 0; +} + +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; diff --git a/sql/wsrep_priv.h b/sql/wsrep_priv.h index 222a49cc2ab..68773d27948 100644 --- a/sql/wsrep_priv.h +++ b/sql/wsrep_priv.h @@ -19,8 +19,9 @@ #ifndef WSREP_PRIV_H #define WSREP_PRIV_H +#include <my_global.h> #include "wsrep_mysqld.h" -#include "../wsrep/wsrep_api.h" +#include "wsrep_schema.h" #include <log.h> #include <pthread.h> @@ -31,25 +32,20 @@ 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; +extern Wsrep_schema* wsrep_schema; // a helper function -bool wsrep_sst_received (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); - -void wsrep_notify_status (wsrep_member_status_t new_status, - const wsrep_view_info_t* view = 0); +void wsrep_sst_received(THD*, const wsrep_uuid_t&, wsrep_seqno_t, + const void*, size_t); + +void wsrep_notify_status(enum wsrep::server_state::state status, + const wsrep::view* view= 0); #endif /* WSREP_PRIV_H */ diff --git a/sql/wsrep_schema.cc b/sql/wsrep_schema.cc new file mode 100644 index 00000000000..98f17e41c94 --- /dev/null +++ b/sql/wsrep_schema.cc @@ -0,0 +1,1360 @@ +/* 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 "mysql/service_wsrep.h" +#include "wsrep_schema.h" +#include "wsrep_applier.h" +#include "wsrep_xid.h" +#include "wsrep_binlog.h" +#include "wsrep_high_priority_service.h" +#include "wsrep_storage_service.h" + +#include <string> +#include <sstream> + +#define WSREP_SCHEMA "mysql" +#define WSREP_STREAMING_TABLE "wsrep_streaming_log" +#define WSREP_CLUSTER_TABLE "wsrep_cluster" +#define WSREP_MEMBERS_TABLE "wsrep_cluster_members" + +const char* wsrep_sr_table_name_full= WSREP_SCHEMA "/" WSREP_STREAMING_TABLE; + +static const std::string wsrep_schema_str= WSREP_SCHEMA; +static const std::string sr_table_str= WSREP_STREAMING_TABLE; +static const std::string cluster_table_str= WSREP_CLUSTER_TABLE; +static const std::string members_table_str= WSREP_MEMBERS_TABLE; + +static const std::string create_cluster_table_str= + "CREATE TABLE IF NOT EXISTS " + wsrep_schema_str + "." + cluster_table_str + + "(" + "cluster_uuid CHAR(36) PRIMARY KEY," + "view_id BIGINT NOT NULL," + "view_seqno BIGINT NOT NULL," + "protocol_version INT NOT NULL," + "capabilities INT NOT NULL" + ") ENGINE=InnoDB"; + +static const std::string create_members_table_str= + "CREATE TABLE IF NOT EXISTS " + wsrep_schema_str + "." + members_table_str + + "(" + "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 cluster_member_history_table_str= "wsrep_cluster_member_history"; +static const std::string create_members_history_table_str= + "CREATE TABLE IF NOT EXISTS " + wsrep_schema_str + "." + cluster_member_history_table_str + + "(" + "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 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_str + "." + cluster_table_str; + +static const std::string delete_from_members_table= + "DELETE FROM " + wsrep_schema_str + "." + members_table_str; + +namespace Wsrep_schema_impl +{ + +class binlog_off +{ +public: + binlog_off(THD* thd) + : m_thd(thd) + , m_option_bits(thd->variables.option_bits) + , m_sql_log_bin(thd->variables.sql_log_bin) + { + thd->variables.option_bits&= ~OPTION_BIN_LOG; + thd->variables.sql_log_bin= 0; + } + ~binlog_off() + { + m_thd->variables.option_bits= m_option_bits; + m_thd->variables.sql_log_bin= m_sql_log_bin; + } +private: + THD* m_thd; + ulonglong m_option_bits; + my_bool m_sql_log_bin; +}; + +class wsrep_off +{ +public: + wsrep_off(THD* thd) + : m_thd(thd) + , m_wsrep_on(thd->variables.wsrep_on) + { + thd->variables.wsrep_on= 0; + } + ~wsrep_off() + { + m_thd->variables.wsrep_on= m_wsrep_on; + } +private: + THD* m_thd; + my_bool m_wsrep_on; +}; + +class thd_context_switch +{ +public: + thd_context_switch(THD *orig_thd, THD *cur_thd) + : m_orig_thd(orig_thd) + , m_cur_thd(cur_thd) + { + m_orig_thd->reset_globals(); + m_cur_thd->store_globals(); + } + ~thd_context_switch() + { + m_cur_thd->reset_globals(); + m_orig_thd->store_globals(); + } +private: + THD *m_orig_thd; + THD *m_cur_thd; +}; + +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) { + thd->reset_for_next_command(); +} + +static void finish_stmt(THD* thd) { + trans_commit_stmt(thd); + close_thread_tables(thd); +} + +static int open_table(THD* thd, + const LEX_CSTRING *schema_name, + const LEX_CSTRING *table_name, + enum thr_lock_type const lock_type, + TABLE** table) { + assert(table); + *table= NULL; + + DBUG_ENTER("Wsrep_schema::open_table()"); + + TABLE_LIST tables; + uint flags= (MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK | + MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY | + MYSQL_OPEN_IGNORE_FLUSH | + MYSQL_LOCK_IGNORE_TIMEOUT); + + tables.init_one_table(schema_name, + table_name, + NULL, lock_type); + + 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= { 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_id& id) { + assert(field < table->s->fields); + std::ostringstream os; + os << id; + table->field[field]->store(os.str().c_str(), + os.str().size(), + &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 void store(TABLE* table, uint field, const std::string& str) +{ + store(table, field, str.c_str(), str.size()); +} + +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); + 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); + 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); + 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); + return 1; + } + return 0; +} + +static int open_for_read(THD* thd, const char* table_name, TABLE** table) { + + 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; +} + +static int scan(TABLE* table, uint field, wsrep::id& id) +{ + assert(field < table->s->fields); + String uuid_str; + (void)table->field[field]->val_str(&uuid_str); + id= wsrep::id(std::string(uuid_str.c_ptr(), uuid_str.length())); + 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, + const Wsrep_id& cluster_uuid, + std::vector<Wsrep_view::member>& members) +{ + Wsrep_id member_id; + char member_name[128]= { 0, }; + char member_incoming[128]= { 0, }; + + 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(members.rbegin()->id() < member_id); + } + + try { + members.push_back(Wsrep_view::member(member_id, + member_name, + member_incoming)); + } + 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: + case HA_ERR_ABORTED_BY_USER: + 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; +} + +/* + 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); +} +} /* namespace Wsrep_schema_impl */ + + +Wsrep_schema::Wsrep_schema() +{ +} + +Wsrep_schema::~Wsrep_schema() +{ } + +static void wsrep_init_thd_for_schema(THD *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; + /* No binlogging */ + thd->variables.sql_log_bin = 0; + thd->variables.option_bits &= ~OPTION_BIN_LOG; + /* No general log */ + thd->variables.option_bits |= OPTION_LOG_OFF; + /* Read committed isolation to avoid gap locking */ + thd->variables.tx_isolation= ISO_READ_COMMITTED; + thd->store_globals(); +} + +int Wsrep_schema::init() +{ + DBUG_ENTER("Wsrep_schema::init()"); + int ret; + THD* thd= new THD(next_thread_id()); + if (!thd) { + WSREP_ERROR("Unable to get thd"); + DBUG_RETURN(1); + } + thd->thread_stack= (char*)&thd; + wsrep_init_thd_for_schema(thd); + + if (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; + } + + delete thd; + DBUG_RETURN(ret); +} + +int Wsrep_schema::store_view(THD* thd, const Wsrep_view& 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_schema_impl::wsrep_off wsrep_off(thd); + Wsrep_schema_impl::binlog_off binlog_off(thd); + + /* + 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_table_str.c_str(), &cluster_table)) + { + goto out; + } + + Wsrep_schema_impl::store(cluster_table, 0, view.state_id().id()); + Wsrep_schema_impl::store(cluster_table, 1, view.view_seqno().get()); + Wsrep_schema_impl::store(cluster_table, 2, view.state_id().seqno().get()); + Wsrep_schema_impl::store(cluster_table, 3, view.protocol_version()); + Wsrep_schema_impl::store(cluster_table, 4, view.capabilities()); + + 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_table_str.c_str(), + &members_table)) + { + WSREP_ERROR("failed to open wsrep.members table"); + goto out; + } + + for (size_t i= 0; i < view.members().size(); ++i) + { + Wsrep_schema_impl::store(members_table, 0, view.members()[i].id()); + Wsrep_schema_impl::store(members_table, 1, view.state_id().id()); + Wsrep_schema_impl::store(members_table, 2, view.members()[i].name()); + Wsrep_schema_impl::store(members_table, 3, 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, cluster_member_history.c_str(), + &members_history_table)) { + WSREP_ERROR("failed to open wsrep.members table"); + goto out; + } + + for (size_t i= 0; i < view.members().size(); ++i) { + Wsrep_schema_impl::store(members_history_table, 0, view.members()[i].id()); + Wsrep_schema_impl::store(members_history_table, 1, view.state_id().id()); + Wsrep_schema_impl::store(members_history_table, 2, view.view_seqno()); + Wsrep_schema_impl::store(members_history_table, 3, view.state_id().seqno()); + Wsrep_schema_impl::store(members_history_table, 4, + view.members()[i].name()); + Wsrep_schema_impl::store(members_history_table, 5, + view.members()[i].incoming()); + if ((error= Wsrep_schema_impl::update_or_insert(members_history_table))) { + WSREP_ERROR("failed to write wsrep_cluster_member_history table: %d", error); + goto out; + } + } + Wsrep_schema_impl::finish_stmt(thd); +#endif /* WSREP_SCHEMA_MEMBERS_HISTORY */ + ret= 0; + out: + + DBUG_RETURN(ret); +} + +Wsrep_view Wsrep_schema::restore_view(THD* thd, const Wsrep_id& own_id) const { + DBUG_ENTER("Wsrep_schema::restore_view()"); + + int ret= 1; + int error; + + TABLE* cluster_table= 0; + bool end_cluster_scan= false; + TABLE* members_table= 0; + bool end_members_scan= false; + + /* variables below need to be initialized in case cluster table is empty */ + Wsrep_id cluster_uuid; + wsrep_seqno_t view_id= -1; + wsrep_seqno_t view_seqno= -1; + int my_idx= -1; + int proto_ver= 0; + wsrep_cap_t capabilities= 0; + std::vector<Wsrep_view::member> members; + + // we don't want causal waits for reading non-replicated private data + int const wsrep_sync_wait_saved= thd->variables.wsrep_sync_wait; + thd->variables.wsrep_sync_wait= 0; + + if (trans_begin(thd, MYSQL_START_TRANS_OPT_READ_ONLY)) { + WSREP_ERROR("wsrep_schema::restore_view(): 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_table_str.c_str(), &cluster_table) || + Wsrep_schema_impl::init_for_scan(cluster_table)) { + goto out; + } + + if (((error= Wsrep_schema_impl::next_record(cluster_table)) != 0 || + 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::scan(cluster_table, 4, capabilities)) && + error != HA_ERR_END_OF_FILE) { + end_cluster_scan= true; + goto out; + } + + if (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_table_str.c_str(), &members_table) || + Wsrep_schema_impl::init_for_scan(members_table)) { + goto out; + } + end_members_scan= true; + + 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; + } + } + + end_members_scan= false; + if (Wsrep_schema_impl::end_scan(members_table)) { + goto out; + } + Wsrep_schema_impl::finish_stmt(thd); + + if (own_id.is_undefined() == false) { + for (uint i= 0; i < members.size(); ++i) { + if (members[i].id() == own_id) { + my_idx= i; + break; + } + } + } + + (void)trans_commit(thd); + ret= 0; /* Success*/ + out: + + if (end_cluster_scan) Wsrep_schema_impl::end_scan(cluster_table); + if (end_members_scan) Wsrep_schema_impl::end_scan(members_table); + + if (0 != ret) { + trans_rollback_stmt(thd); + if (!trans_rollback(thd)) { + close_thread_tables(thd); + } + } + thd->mdl_context.release_transactional_locks(); + + thd->variables.wsrep_sync_wait= wsrep_sync_wait_saved; + + if (0 == ret) { + Wsrep_view ret_view( + wsrep::gtid(cluster_uuid, Wsrep_seqno(view_seqno)), + Wsrep_seqno(view_id), + wsrep::view::primary, + capabilities, + my_idx, + proto_ver, + members + ); + + if (wsrep_debug) { + std::ostringstream os; + os << "Restored cluster view:\n" << ret_view; + WSREP_INFO("%s", os.str().c_str()); + } + DBUG_RETURN(ret_view); + } + else + { + WSREP_ERROR("wsrep_schema::restore_view() failed."); + Wsrep_view ret_view; + DBUG_RETURN(ret_view); + } +} + +int Wsrep_schema::append_fragment(THD* thd, + const wsrep::id& server_id, + wsrep::transaction_id transaction_id, + wsrep::seqno seqno, + int flags, + const wsrep::const_buffer& data) +{ + DBUG_ENTER("Wsrep_schema::append_fragment"); + std::ostringstream os; + os << server_id; + WSREP_DEBUG("Append fragment(%llu) %s, %llu", + thd->thread_id, + os.str().c_str(), + transaction_id.get()); + Wsrep_schema_impl::binlog_off binlog_off(thd); + Wsrep_schema_impl::init_stmt(thd); + + TABLE* frag_table= 0; + if (Wsrep_schema_impl::open_for_write(thd, sr_table_str.c_str(), &frag_table)) + { + trans_rollback_stmt(thd); + DBUG_RETURN(1); + } + + Wsrep_schema_impl::store(frag_table, 0, server_id); + Wsrep_schema_impl::store(frag_table, 1, transaction_id.get()); + Wsrep_schema_impl::store(frag_table, 2, seqno.get()); + Wsrep_schema_impl::store(frag_table, 3, flags); + Wsrep_schema_impl::store(frag_table, 4, data.data(), data.size()); + + int error; + if ((error= Wsrep_schema_impl::insert(frag_table))) { + WSREP_ERROR("Failed to write to frag table: %d", error); + trans_rollback_stmt(thd); + DBUG_RETURN(1); + } + Wsrep_schema_impl::finish_stmt(thd); + DBUG_RETURN(0); +} + +int Wsrep_schema::update_fragment_meta(THD* thd, + const wsrep::ws_meta& ws_meta) +{ + DBUG_ENTER("Wsrep_schema::update_fragment_meta"); + std::ostringstream os; + os << ws_meta.server_id(); + WSREP_DEBUG("update_frag_seqno(%llu) %s, %llu, seqno %lld", + thd->thread_id, + os.str().c_str(), + ws_meta.transaction_id().get(), + ws_meta.seqno().get()); + DBUG_ASSERT(ws_meta.seqno().is_undefined() == false); + + Wsrep_schema_impl::binlog_off binlog_off(thd); + int error; + uchar key[MAX_KEY_LENGTH]; + key_part_map key_map= 0; + TABLE* frag_table= 0; + + Wsrep_schema_impl::init_stmt(thd); + if (Wsrep_schema_impl::open_for_write(thd, sr_table_str.c_str(), &frag_table)) + { + DBUG_RETURN(1); + } + + /* Find record with the given uuid, trx id, and seqno -1 */ + Wsrep_schema_impl::store(frag_table, 0, ws_meta.server_id()); + Wsrep_schema_impl::store(frag_table, 1, ws_meta.transaction_id().get()); + 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_WARN("Record not found in %s.%s: %d", + frag_table->s->db.str, + frag_table->s->table_name.str, + error); + } + Wsrep_schema_impl::finish_stmt(thd); + DBUG_RETURN(1); + } + + /* 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, ws_meta.seqno().get()); + 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); + Wsrep_schema_impl::finish_stmt(thd); + DBUG_RETURN(1); + } + + int ret= Wsrep_schema_impl::end_index_scan(frag_table); + Wsrep_schema_impl::finish_stmt(thd); + DBUG_RETURN(ret); +} + +static int remove_fragment(THD* thd, + TABLE* frag_table, + const wsrep::id& server_id, + wsrep::transaction_id transaction_id, + wsrep::seqno seqno) +{ + WSREP_DEBUG("remove_fragment(%llu) trx %llu, seqno %lld", + thd->thread_id, + transaction_id.get(), + seqno.get()); + int ret= 0; + int error; + uchar key[MAX_KEY_LENGTH]; + key_part_map key_map= 0; + + DBUG_ASSERT(server_id.is_undefined() == false); + DBUG_ASSERT(transaction_id.is_undefined() == false); + DBUG_ASSERT(seqno.is_undefined() == false); + + /* + 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, server_id); + Wsrep_schema_impl::store(frag_table, 1, transaction_id.get()); + Wsrep_schema_impl::store(frag_table, 2, seqno.get()); + 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_DEBUG("Record not found in %s.%s:trx %llu, seqno %lld, error %d", + frag_table->s->db.str, + frag_table->s->table_name.str, + transaction_id.get(), + seqno.get(), + error); + } + ret= error; + } + else if (Wsrep_schema_impl::delete_row(frag_table)) + { + ret= 1; + } + + Wsrep_schema_impl::end_index_scan(frag_table); + return ret; +} + +int Wsrep_schema::remove_fragments(THD* thd, + const wsrep::id& server_id, + wsrep::transaction_id transaction_id, + const std::vector<wsrep::seqno>& fragments) +{ + DBUG_ENTER("Wsrep_schema::remove_fragments"); + int ret= 0; + + WSREP_DEBUG("Removing %zu fragments", fragments.size()); + Wsrep_schema_impl::wsrep_off wsrep_off(thd); + Wsrep_schema_impl::binlog_off binlog_off(thd); + + /* + Open SR table for write. + Adopted from Rpl_info_table_access::open_table() + */ + uint flags= (MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK | + MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY | + MYSQL_OPEN_IGNORE_FLUSH | + MYSQL_LOCK_IGNORE_TIMEOUT); + Query_tables_list query_tables_list_backup; + Open_tables_backup open_tables_backup; + thd->lex->reset_n_backup_query_tables_list(&query_tables_list_backup); + thd->reset_n_backup_open_tables_state(&open_tables_backup); + TABLE_LIST tables; + LEX_CSTRING schema_str= { wsrep_schema_str.c_str(), wsrep_schema_str.length() }; + LEX_CSTRING table_str= { sr_table_str.c_str(), sr_table_str.length() }; + tables.init_one_table(&schema_str, + &table_str, 0, TL_WRITE); + + if (!open_n_lock_single_table(thd, &tables, tables.lock_type, flags)) + { + WSREP_DEBUG("Failed to open SR table for access"); + ret= 1; + } + else + { + tables.table->use_all_columns(); + for (std::vector<wsrep::seqno>::const_iterator i= fragments.begin(); + i != fragments.end(); ++i) + { + if (remove_fragment(thd, + tables.table, + server_id, + transaction_id, *i)) + { + ret= 1; + break; + } + } + } + close_thread_tables(thd); + thd->restore_backup_open_tables_state(&open_tables_backup); + thd->lex->restore_backup_query_tables_list(&query_tables_list_backup); + + if (thd->wsrep_cs().mode() == wsrep::client_state::m_local && + !thd->in_multi_stmt_transaction_mode()) + { + /* + The ugly part: Locally executing autocommit statement is + committing and it has removed a fragment from stable storage. + Now calling finish_stmt() will call trans_commit_stmt(), which will + actually commit the transaction, what we really don't want + to do at this point. + + Doing nothing at this point seems to work ok, this block is + intentionally no-op and for documentation purposes only. + */ + } + else + { + Wsrep_schema_impl::finish_stmt(thd); + } + + DBUG_RETURN(ret); +} + +int Wsrep_schema::replay_transaction(THD* thd, + Relay_log_info* rli, + const wsrep::ws_meta& ws_meta, + const std::vector<wsrep::seqno>& fragments) +{ + DBUG_ENTER("Wsrep_schema::replay_transaction"); + DBUG_ASSERT(!fragments.empty()); + + Wsrep_schema_impl::wsrep_off wsrep_off(thd); + Wsrep_schema_impl::binlog_off binlog_off(thd); + + int ret= 1; + int error; + TABLE* frag_table= 0; + uchar key[MAX_KEY_LENGTH]; + key_part_map key_map= 0; + + for (std::vector<wsrep::seqno>::const_iterator i= fragments.begin(); + i != fragments.end(); ++i) + { + Wsrep_schema_impl::init_stmt(thd); + if ((error= Wsrep_schema_impl::open_for_read(thd, sr_table_str.c_str(), &frag_table))) + { + WSREP_WARN("Could not open SR table for read: %d", error); + Wsrep_schema_impl::finish_stmt(thd); + DBUG_RETURN(1); + } + + Wsrep_schema_impl::store(frag_table, 0, ws_meta.server_id()); + Wsrep_schema_impl::store(frag_table, 1, ws_meta.transaction_id().get()); + Wsrep_schema_impl::store(frag_table, 2, i->get()); + Wsrep_schema_impl::make_key(frag_table, key, &key_map, 3); + + int error= Wsrep_schema_impl::init_for_index_scan(frag_table, + key, + key_map); + if (error) + { + WSREP_WARN("Failed to init streaming log table for index scan: %d", + error); + Wsrep_schema_impl::end_index_scan(frag_table); + ret= 1; + break; + } + + int flags; + Wsrep_schema_impl::scan(frag_table, 3, flags); + WSREP_DEBUG("replay_fragment(%llu): seqno: %lld flags: %x", + ws_meta.transaction_id().get(), + i->get(), + flags); + String buf; + frag_table->field[4]->val_str(&buf); + + Wsrep_schema_impl::end_index_scan(frag_table); + Wsrep_schema_impl::finish_stmt(thd); + ret= wsrep_apply_events(thd, rli, buf.c_ptr_safe(), buf.length()); + if (ret) + { + WSREP_WARN("Wsrep_schema::replay_transaction: failed to apply fragments"); + break; + } + Wsrep_schema_impl::init_stmt(thd); + + if ((error= Wsrep_schema_impl::open_for_write(thd, sr_table_str.c_str(), &frag_table))) + { + WSREP_WARN("Could not open SR table for write: %d", error); + Wsrep_schema_impl::finish_stmt(thd); + DBUG_RETURN(1); + } + error= Wsrep_schema_impl::init_for_index_scan(frag_table, + key, + key_map); + if (error) + { + WSREP_WARN("Failed to init streaming log table for index scan: %d", + error); + Wsrep_schema_impl::end_index_scan(frag_table); + ret= 1; + break; + } + + error= Wsrep_schema_impl::delete_row(frag_table); + if (error) + { + WSREP_WARN("Could not delete row from streaming log table: %d", error); + Wsrep_schema_impl::end_index_scan(frag_table); + ret= 1; + break; + } + Wsrep_schema_impl::end_index_scan(frag_table); + Wsrep_schema_impl::finish_stmt(thd); + } + + DBUG_RETURN(ret); +} + +int Wsrep_schema::recover_sr_transactions(THD *orig_thd) +{ + DBUG_ENTER("Wsrep_schema::recover_sr_transactions"); + THD storage_thd(true, true); + storage_thd.thread_stack= (orig_thd ? orig_thd->thread_stack : + (char*) &storage_thd); + TABLE* frag_table= 0; + TABLE* cluster_table= 0; + Wsrep_storage_service storage_service(&storage_thd); + Wsrep_schema_impl::binlog_off binlog_off(&storage_thd); + Wsrep_schema_impl::wsrep_off binglog_off(&storage_thd); + Wsrep_schema_impl::thd_context_switch thd_context_switch(orig_thd, + &storage_thd); + Wsrep_server_state& server_state(Wsrep_server_state::instance()); + + int ret= 1; + int error; + wsrep::id cluster_id; + + Wsrep_schema_impl::init_stmt(&storage_thd); + storage_thd.wsrep_skip_locking= FALSE; + /* + Open the table for reading and writing so that fragments without + valid seqno can be deleted. + */ + if (Wsrep_schema_impl::open_for_write(&storage_thd, + cluster_table_str.c_str(), + &cluster_table) || + Wsrep_schema_impl::init_for_scan(cluster_table)) + { + Wsrep_schema_impl::finish_stmt(&storage_thd); + DBUG_RETURN(1); + } + + if ((error= Wsrep_schema_impl::next_record(cluster_table))) + { + Wsrep_schema_impl::end_scan(cluster_table); + Wsrep_schema_impl::finish_stmt(&storage_thd); + trans_commit(&storage_thd); + if (error == HA_ERR_END_OF_FILE) + { + WSREP_INFO("Cluster table is empty, not recovering transactions"); + DBUG_RETURN(0); + } + else + { + WSREP_ERROR("Failed to read cluster table: %d", error); + DBUG_RETURN(1); + } + } + + Wsrep_schema_impl::scan(cluster_table, 0, cluster_id); + Wsrep_schema_impl::end_scan(cluster_table); + Wsrep_schema_impl::finish_stmt(&storage_thd); + + std::ostringstream os; + os << cluster_id; + WSREP_INFO("Recovered cluster id %s", os.str().c_str()); + + storage_thd.wsrep_skip_locking= TRUE; + Wsrep_schema_impl::init_stmt(&storage_thd); + if (Wsrep_schema_impl::open_for_read(&storage_thd, sr_table_str.c_str(), &frag_table) || + Wsrep_schema_impl::init_for_scan(frag_table)) + { + WSREP_ERROR("Failed to open SR table for read"); + goto out; + } + + while (true) + { + if ((error= Wsrep_schema_impl::next_record(frag_table)) == 0) + { + wsrep::id server_id; + Wsrep_schema_impl::scan(frag_table, 0, server_id); + wsrep::client_id client_id; + unsigned long long transaction_id_ull; + Wsrep_schema_impl::scan(frag_table, 1, transaction_id_ull); + wsrep::transaction_id transaction_id(transaction_id_ull); + long long seqno_ll; + Wsrep_schema_impl::scan(frag_table, 2, seqno_ll); + wsrep::seqno seqno(seqno_ll); + + /* This is possible if the server crashes between inserting the + fragment into table and updating the fragment seqno after + certification. */ + if (seqno.is_undefined()) + { + Wsrep_schema_impl::delete_row(frag_table); + continue; + } + + wsrep::gtid gtid(cluster_id, seqno); + int flags; + Wsrep_schema_impl::scan(frag_table, 3, flags); + String data_str; + + (void)frag_table->field[4]->val_str(&data_str); + wsrep::const_buffer data(data_str.c_ptr(), data_str.length()); + wsrep::ws_meta ws_meta(gtid, + wsrep::stid(server_id, + transaction_id, + client_id), + wsrep::seqno::undefined(), + flags); + + wsrep::high_priority_service* applier; + if (!(applier= server_state.find_streaming_applier(server_id, + transaction_id))) + { + DBUG_ASSERT(wsrep::starts_transaction(flags)); + THD* thd= new THD(true, true); + thd->thread_stack= (char*)&storage_thd; + + mysql_mutex_lock(&LOCK_thread_count); + thd->thread_id= next_thread_id(); + thd->real_id= pthread_self(); + mysql_mutex_unlock(&LOCK_thread_count); + + applier= new Wsrep_applier_service(thd); + server_state.start_streaming_applier(server_id, transaction_id, + applier); + applier->start_transaction(wsrep::ws_handle(transaction_id, 0), + ws_meta); + } + applier->store_globals(); + applier->apply_write_set(ws_meta, data); + applier->after_apply(); + storage_service.store_globals(); + } + else if (error == HA_ERR_END_OF_FILE) + { + ret= 0; + break; + } + else + { + WSREP_ERROR("SR table scan returned error %d", error); + break; + } + } + Wsrep_schema_impl::end_scan(frag_table); + Wsrep_schema_impl::finish_stmt(&storage_thd); + trans_commit(&storage_thd); +out: + DBUG_RETURN(ret); +} diff --git a/sql/wsrep_schema.h b/sql/wsrep_schema.h new file mode 100644 index 00000000000..fb5eaa8931f --- /dev/null +++ b/sql/wsrep_schema.h @@ -0,0 +1,161 @@ +/* Copyright (C) 2015-2018 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 + +/* wsrep-lib */ +#include "wsrep_types.h" + + +#include "mysqld.h" +#include "thr_lock.h" /* enum thr_lock_type */ +#include "wsrep_mysqld.h" + +#include <string> + +/* + Forward decls +*/ +class THD; +class Relay_log_info; +struct TABLE; +struct TABLE_LIST; +struct st_mysql_lex_string; +typedef struct st_mysql_lex_string LEX_STRING; + +/** 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 char* wsrep_sr_table_name_full; + +class Wsrep_schema +{ + public: + + Wsrep_schema(); + ~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(THD*, const Wsrep_view& view); + + /* + Restore view info from stable storage. + */ + Wsrep_view restore_view(THD* thd, const Wsrep_id& own_id) 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); + /** + Append transaction fragment to fragment storage. + Transaction must have been started for THD before this call. + In order to make changes durable, transaction must be committed + separately after this call. + + @param thd THD object + @param server_id Wsrep server identifier + @param transaction_id Transaction identifier + @param flags Flags for the fragment + @param data Fragment data buffer + + @return Zero in case of success, non-zero on failure. + */ + int append_fragment(THD* thd, + const wsrep::id& server_id, + wsrep::transaction_id transaction_id, + wsrep::seqno seqno, + int flags, + const wsrep::const_buffer& data); + /** + Update existing fragment meta data. The fragment must have been + inserted before using append_fragment(). + + @param thd THD object + @param ws_meta Wsrep meta data + + @return Zero in case of success, non-zero on failure. + */ + int update_fragment_meta(THD* thd, + const wsrep::ws_meta& ws_meta); + + /** + Remove fragments from storage. This method must be called + inside active transaction. Fragment removal will be committed + once the transaction commits. + + @param thd Pointer to THD object + @param server_id Identifier of the running server + @param transaction_id Identifier of the current transaction + @param fragments Vector of fragment seqnos to be removed + */ + int remove_fragments(THD* thd, + const wsrep::id& server_id, + wsrep::transaction_id transaction_id, + const std::vector<wsrep::seqno>& fragments); + + /** + Replay a transaction from stored fragments. The caller must have + started a transaction for a thd. + + @param thd Pointer to THD object + @param ws_meta Write set meta data for commit fragment. + @param fragments Vector of fragments to be replayed + + @return Zero on success, non-zero on failure. + */ + int replay_transaction(THD* thd, + Relay_log_info* rli, + const wsrep::ws_meta& ws_meta, + const std::vector<wsrep::seqno>& fragments); + + /** + Recover streaming transactions from SR table. + This method should be called after storage enignes are initialized. + It will scan SR table and replay found streaming transactions. + + @param orig_thd The THD object of the calling thread. + + @return Zero on success, non-zero on failure. + */ + int recover_sr_transactions(THD* orig_thd); + + /* + Close wsrep schema. + */ + void close(); + + private: + /* Non-copyable */ + Wsrep_schema(const Wsrep_schema&); + Wsrep_schema& operator=(const Wsrep_schema&); +}; + +extern Wsrep_schema* wsrep_schema; + +#endif /* !WSREP_SCHEMA_H */ diff --git a/sql/wsrep_server_service.cc b/sql/wsrep_server_service.cc new file mode 100644 index 00000000000..7efff35f2b1 --- /dev/null +++ b/sql/wsrep_server_service.cc @@ -0,0 +1,318 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "my_global.h" +#include "wsrep_server_service.h" +#include "wsrep_server_state.h" +#include "wsrep_client_state.h" +#include "wsrep_client_service.h" +#include "wsrep_storage_service.h" +#include "wsrep_high_priority_service.h" + +#include "wsrep_sst.h" +#include "wsrep_xid.h" +#include "wsrep_mysqld.h" +#include "wsrep_schema.h" +#include "wsrep_utils.h" + +#include "log.h" /* sql_print_xxx() */ +#include "sql_class.h" /* system variables */ +#include "transaction.h" /* trans_xxx */ +#include "sql_base.h" /* close_thread_tables */ + +static void init_service_thd(THD* thd, char* thread_stack) +{ + thd->thread_stack= thread_stack; + thd->real_id= pthread_self(); + thd->prior_thr_create_utime= thd->start_utime= microsecond_interval_timer(); + thd->set_command(COM_SLEEP); + thd->reset_for_next_command(true); +} + +wsrep::storage_service* Wsrep_server_service::storage_service( + wsrep::client_service& client_service) +{ + Wsrep_client_service& cs= + static_cast<Wsrep_client_service&>(client_service); + THD* thd= new THD(next_thread_id(), true, true); + init_service_thd(thd, cs.m_thd->thread_stack); + WSREP_DEBUG("Created storage service with thread id %llu", + thd->thread_id); + return new Wsrep_storage_service(thd); +} + +wsrep::storage_service* Wsrep_server_service::storage_service( + wsrep::high_priority_service& high_priority_service) +{ + Wsrep_high_priority_service& hps= + static_cast<Wsrep_high_priority_service&>(high_priority_service); + THD* thd= new THD(next_thread_id(), true, true); + init_service_thd(thd, hps.m_thd->thread_stack); + WSREP_DEBUG("Created high priority storage service with thread id %llu", + thd->thread_id); + return new Wsrep_storage_service(thd); +} + +void Wsrep_server_service::release_storage_service( + wsrep::storage_service* storage_service) +{ + Wsrep_storage_service* ss= + static_cast<Wsrep_storage_service*>(storage_service); + THD* thd= ss->m_thd; + delete ss; + delete thd; +} + +wsrep::high_priority_service* +Wsrep_server_service::streaming_applier_service( + wsrep::client_service& orig_client_service) +{ + Wsrep_client_service& orig_cs= + static_cast<Wsrep_client_service&>(orig_client_service); + THD* thd= new THD(next_thread_id(), true, true); + init_service_thd(thd, orig_cs.m_thd->thread_stack); + WSREP_DEBUG("Created streaming applier service in local context with " + "thread id %llu", thd->thread_id); + return new Wsrep_applier_service(thd); +} + +wsrep::high_priority_service* +Wsrep_server_service::streaming_applier_service( + wsrep::high_priority_service& orig_high_priority_service) +{ + Wsrep_high_priority_service& + orig_hps(static_cast<Wsrep_high_priority_service&>(orig_high_priority_service)); + THD* thd= new THD(next_thread_id(), true, true); + init_service_thd(thd, orig_hps.m_thd->thread_stack); + WSREP_DEBUG("Created streaming applier service in high priority " + "context with thread id %llu", thd->thread_id); + return new Wsrep_applier_service(thd); +} + +void Wsrep_server_service::release_high_priority_service(wsrep::high_priority_service* high_priority_service) +{ + Wsrep_high_priority_service* hps= + static_cast<Wsrep_high_priority_service*>(high_priority_service); + THD* thd= hps->m_thd; + delete hps; + delete thd; +} + +void Wsrep_server_service::background_rollback(wsrep::client_state& client_state) +{ + Wsrep_client_state& cs= static_cast<Wsrep_client_state&>(client_state); + wsrep_fire_rollbacker(cs.thd()); +} + +void Wsrep_server_service::bootstrap() +{ + wsrep::log_info() + << "Bootstrapping a new cluster, setting initial position to " + << wsrep::gtid::undefined(); + wsrep_set_SE_checkpoint(wsrep::gtid::undefined()); +} + +void Wsrep_server_service::log_message(enum wsrep::log::level level, + const char* message) +{ + switch (level) + { + case wsrep::log::debug: + sql_print_information("debug: %s", message); + break; + case wsrep::log::info: + sql_print_information("%s", message); + break; + case wsrep::log::warning: + sql_print_warning("%s", message); + break; + case wsrep::log::error: + sql_print_error("%s", message); + break; + } +} + +void Wsrep_server_service::log_view( + wsrep::high_priority_service* high_priority_service, + const wsrep::view& view) +{ + Wsrep_high_priority_service* applier= + static_cast<Wsrep_high_priority_service*>(high_priority_service); + /* Update global system variables */ + mysql_mutex_lock(&LOCK_global_system_variables); + if (wsrep_auto_increment_control && view.own_index() >= 0) + { + global_system_variables.auto_increment_offset= view.own_index() + 1; + global_system_variables.auto_increment_increment= view.members().size(); + wsrep_protocol_version= view.protocol_version(); + } + mysql_mutex_unlock(&LOCK_global_system_variables); + + /* Update wsrep status variables */ + mysql_mutex_lock(&LOCK_status); + wsrep_cluster_size= view.members().size(); + wsrep_local_index= view.own_index(); + std::ostringstream os; + os << view.state_id().id(); + wsrep_update_cluster_state_uuid(os.str().c_str()); + mysql_mutex_unlock(&LOCK_status); + wsrep_config_state->set(view); + + if (view.status() == wsrep::view::primary) + { + if (applier) + { + Wsrep_id id; + Wsrep_view prev_view= wsrep_schema->restore_view(applier->m_thd, id); + if (prev_view.state_id().id() != view.state_id().id()) + { + WSREP_DEBUG("New cluster UUID was generated, resetting position info"); + wsrep_set_SE_checkpoint(wsrep::gtid::undefined()); + } + + if (wsrep_debug) + { + std::ostringstream os; + os << "Storing cluster view:\n" << view; + WSREP_INFO("%s", os.str().c_str()); + DBUG_ASSERT(prev_view.state_id().id() != view.state_id().id() || + view.state_id().seqno() > prev_view.state_id().seqno()); + } + + if (trans_begin(applier->m_thd, MYSQL_START_TRANS_OPT_READ_WRITE)) + { + WSREP_WARN("Failed to start transaction for store view"); + } + else + { + if (wsrep_schema->store_view(applier->m_thd, view)) + { + WSREP_WARN("Failed to store view"); + trans_rollback_stmt(applier->m_thd); + if (!trans_rollback(applier->m_thd)) + { + close_thread_tables(applier->m_thd); + } + } + else + { + if (trans_commit(applier->m_thd)) + { + WSREP_WARN("Failed to commit transaction for store view"); + } + } + applier->m_thd->mdl_context.release_transactional_locks(); + } + + wsrep_set_SE_checkpoint(view.state_id()); + DBUG_ASSERT(wsrep_get_SE_checkpoint().id() == view.state_id().id()); + } + else + { + WSREP_DEBUG("No applier in Wsrep_server_service::log_view(), " + "skipping write to wsrep_schema"); + } + } +} + +void Wsrep_server_service::recover_streaming_appliers(wsrep::client_service& cs) +{ + Wsrep_client_service& client_service= static_cast<Wsrep_client_service&>(cs); + wsrep_recover_sr_from_storage(client_service.m_thd); +} + +void Wsrep_server_service::recover_streaming_appliers( + wsrep::high_priority_service& hs) +{ + Wsrep_high_priority_service& high_priority_service= + static_cast<Wsrep_high_priority_service&>(hs); + wsrep_recover_sr_from_storage(high_priority_service.m_thd); +} + +wsrep::view Wsrep_server_service::get_view(wsrep::client_service& c, + const wsrep::id& own_id) +{ + Wsrep_client_service& cs(static_cast<Wsrep_client_service&>(c)); + wsrep::view v(wsrep_schema->restore_view(cs.m_thd, own_id)); + return v; +} + +wsrep::gtid Wsrep_server_service::get_position(wsrep::client_service&) +{ + return wsrep_get_SE_checkpoint(); +} + +void Wsrep_server_service::log_state_change( + enum Wsrep_server_state::state prev_state, + enum Wsrep_server_state::state current_state) +{ + WSREP_INFO("Server status change %s -> %s", + wsrep::to_c_string(prev_state), + wsrep::to_c_string(current_state)); + mysql_mutex_lock(&LOCK_status); + switch (current_state) + { + case Wsrep_server_state::s_synced: + wsrep_ready= TRUE; + WSREP_INFO("Synchronized with group, ready for connections"); + /* fall through */ + case Wsrep_server_state::s_joined: + case Wsrep_server_state::s_donor: + wsrep_cluster_status= "Primary"; + break; + case Wsrep_server_state::s_connected: + wsrep_cluster_status= "non-Primary"; + wsrep_ready= FALSE; + wsrep_connected= TRUE; + break; + case Wsrep_server_state::s_disconnected: + wsrep_ready= FALSE; + wsrep_connected= FALSE; + wsrep_cluster_status= "Disconnected"; + break; + default: + wsrep_ready= FALSE; + wsrep_cluster_status= "non-Primary"; + break; + } + mysql_mutex_unlock(&LOCK_status); + wsrep_config_state->set(current_state); +} + +bool Wsrep_server_service::sst_before_init() const +{ + return wsrep_before_SE(); +} + +std::string Wsrep_server_service::sst_request() +{ + return wsrep_sst_prepare(); +} + +int Wsrep_server_service::start_sst(const std::string& sst_request, + const wsrep::gtid& gtid, + bool bypass) +{ + return wsrep_sst_donate(sst_request, gtid, bypass); +} + +int Wsrep_server_service::wait_committing_transactions(int timeout) +{ + return wsrep_wait_committing_connections_close(timeout); +} + +void Wsrep_server_service::debug_sync(const char*) +{ +} diff --git a/sql/wsrep_server_service.h b/sql/wsrep_server_service.h new file mode 100644 index 00000000000..b8f1f009cde --- /dev/null +++ b/sql/wsrep_server_service.h @@ -0,0 +1,81 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef WSREP_SERVER_SERVICE_H +#define WSREP_SERVER_SERVICE_H + +/* wsrep-lib */ +#include "wsrep/server_service.hpp" +#include "wsrep/exception.hpp" // not_impemented_error(), remove when finished +#include "wsrep/storage_service.hpp" + +class Wsrep_server_state; + + +/* wsrep::server_service interface implementation */ +class Wsrep_server_service : public wsrep::server_service +{ +public: + Wsrep_server_service(Wsrep_server_state& server_state) + : m_server_state(server_state) + { } + + wsrep::storage_service* storage_service(wsrep::client_service&); + + wsrep::storage_service* storage_service(wsrep::high_priority_service&); + + void release_storage_service(wsrep::storage_service*); + + wsrep::high_priority_service* + streaming_applier_service(wsrep::client_service&); + + wsrep::high_priority_service* + streaming_applier_service(wsrep::high_priority_service&); + + void release_high_priority_service(wsrep::high_priority_service*); + + void background_rollback(wsrep::client_state&); + + void bootstrap(); + void log_message(enum wsrep::log::level, const char*); + + void log_dummy_write_set(wsrep::client_state&, const wsrep::ws_meta&) + { throw wsrep::not_implemented_error(); } + + void log_view(wsrep::high_priority_service*, const wsrep::view&); + + void recover_streaming_appliers(wsrep::client_service&); + void recover_streaming_appliers(wsrep::high_priority_service&); + wsrep::view get_view(wsrep::client_service&, const wsrep::id& own_id); + + wsrep::gtid get_position(wsrep::client_service&); + + void log_state_change(enum wsrep::server_state::state, + enum wsrep::server_state::state); + + bool sst_before_init() const; + + std::string sst_request(); + int start_sst(const std::string&, const wsrep::gtid&, bool); + + int wait_committing_transactions(int); + + void debug_sync(const char*); +private: + Wsrep_server_state& m_server_state; +}; + + +#endif /* WSREP_SERVER_SERVICE */ diff --git a/sql/wsrep_server_state.cc b/sql/wsrep_server_state.cc new file mode 100644 index 00000000000..4571201b07d --- /dev/null +++ b/sql/wsrep_server_state.cc @@ -0,0 +1,82 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "my_global.h" +#include "wsrep_api.h" +#include "wsrep_server_state.h" + +mysql_mutex_t LOCK_wsrep_server_state; +mysql_cond_t COND_wsrep_server_state; + +#ifdef HAVE_PSI_INTERFACE +PSI_mutex_key key_LOCK_wsrep_server_state; +PSI_cond_key key_COND_wsrep_server_state; +#endif + +Wsrep_server_state::Wsrep_server_state(const std::string& name, + const std::string& incoming_address, + const std::string& address, + const std::string& working_dir, + const wsrep::gtid& initial_position, + int max_protocol_version) + : wsrep::server_state(m_mutex, + m_cond, + m_service, + name, + incoming_address, + address, + working_dir, + initial_position, + max_protocol_version, + wsrep::server_state::rm_sync) + , m_mutex(LOCK_wsrep_server_state) + , m_cond(COND_wsrep_server_state) + , m_service(*this) +{ + +} + +void Wsrep_server_state::init_once(const std::string& name, + const std::string& incoming_address, + const std::string& address, + const std::string& working_dir, + const wsrep::gtid& initial_position, + int max_protocol_version) +{ + if (m_instance == 0) + { + mysql_mutex_init(key_LOCK_wsrep_server_state, &LOCK_wsrep_server_state, + MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_wsrep_server_state, &COND_wsrep_server_state, 0); + m_instance = new Wsrep_server_state(name, + incoming_address, + address, + working_dir, + initial_position, + max_protocol_version); + } +} + +void Wsrep_server_state::destroy() +{ + + if (m_instance) + { + delete m_instance; + m_instance= 0; + mysql_mutex_destroy(&LOCK_wsrep_server_state); + mysql_cond_destroy(&COND_wsrep_server_state); + } +} diff --git a/sql/wsrep_server_state.h b/sql/wsrep_server_state.h new file mode 100644 index 00000000000..d0946498d56 --- /dev/null +++ b/sql/wsrep_server_state.h @@ -0,0 +1,66 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef WSREP_SERVER_STATE_H +#define WSREP_SERVER_STATE_H + +/* wsrep-lib */ +#include "wsrep/server_state.hpp" +#include "wsrep/provider.hpp" + +/* implementation */ +#include "wsrep_server_service.h" +#include "wsrep_mutex.h" +#include "wsrep_condition_variable.h" + +class Wsrep_server_state : public wsrep::server_state +{ +public: + static void init_once(const std::string& name, + const std::string& incoming_address, + const std::string& address, + const std::string& working_dir, + const wsrep::gtid& initial_position, + int max_protocol_version); + static void destroy(); + static Wsrep_server_state& instance() + { + return *m_instance; + } + + static wsrep::provider& get_provider() + { + return instance().provider(); + } + + static bool has_capability(int capability) + { + return (get_provider().capabilities() & capability); + } +private: + Wsrep_server_state(const std::string& name, + const std::string& incoming_address, + const std::string& address, + const std::string& working_dir, + const wsrep::gtid& initial_position, + int max_protocol_version); + Wsrep_mutex m_mutex; + Wsrep_condition_variable m_cond; + Wsrep_server_service m_service; + + static Wsrep_server_state* m_instance; +}; + +#endif // WSREP_SERVER_STATE_H diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 0a2424fa069..4e3a7072629 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 @@ -35,16 +35,16 @@ static char wsrep_defaults_file[FN_REFLEN * 2 + 10 + 30 + sizeof(WSREP_SST_OPT_CONF) + sizeof(WSREP_SST_OPT_CONF_SUFFIX) + - sizeof(WSREP_SST_OPT_CONF_EXTRA)] = {0}; + sizeof(WSREP_SST_OPT_CONF_EXTRA)]= {0}; -const char* wsrep_sst_method = WSREP_SST_DEFAULT; -const char* wsrep_sst_receive_address = WSREP_SST_ADDRESS_AUTO; -const char* wsrep_sst_donor = ""; -const char* wsrep_sst_auth = NULL; +const char* wsrep_sst_method = WSREP_SST_DEFAULT; +const char* wsrep_sst_receive_address= WSREP_SST_ADDRESS_AUTO; +const char* wsrep_sst_donor = ""; +const char* wsrep_sst_auth = NULL; // container for real auth string -static const char* sst_auth_real = NULL; -my_bool wsrep_sst_donor_rejects_queries = FALSE; +static const char* sst_auth_real = NULL; +my_bool wsrep_sst_donor_rejects_queries= FALSE; bool wsrep_sst_method_check (sys_var *self, THD* thd, set_var* var) { @@ -65,7 +65,7 @@ bool wsrep_sst_method_update (sys_var *self, THD* thd, enum_var_type type) return 0; } -static const char* data_home_dir = NULL; +static const char* data_home_dir= NULL; void wsrep_set_data_home_dir(const char *data_dir) { @@ -139,7 +139,7 @@ static bool sst_auth_real_set (const char* value) { // set sst_auth_real if (sst_auth_real) { my_free((void *) sst_auth_real); } - sst_auth_real = v; + sst_auth_real= v; // mask wsrep_sst_auth if (strlen(sst_auth_real)) @@ -180,6 +180,7 @@ bool wsrep_sst_donor_update (sys_var *self, THD* thd, enum_var_type type) return 0; } + bool wsrep_before_SE() { return (wsrep_provider != NULL @@ -188,111 +189,29 @@ bool wsrep_before_SE() && strcmp (wsrep_sst_method, WSREP_SST_MYSQLDUMP)); } -static bool sst_complete = false; -static bool sst_needed = false; - -#define WSREP_EXTEND_TIMEOUT_INTERVAL 30 -#define WSREP_TIMEDWAIT_SECONDS 10 - -void wsrep_sst_grab () -{ - WSREP_INFO("wsrep_sst_grab()"); - if (mysql_mutex_lock (&LOCK_wsrep_sst)) abort(); - sst_complete = false; - mysql_mutex_unlock (&LOCK_wsrep_sst); -} - -// Wait for end of SST -bool wsrep_sst_wait () -{ - double total_wtime = 0; - - if (mysql_mutex_lock (&LOCK_wsrep_sst)) - abort(); - - WSREP_INFO("Waiting for SST to complete."); - - while (!sst_complete) - { - struct timespec wtime; - set_timespec(wtime, WSREP_TIMEDWAIT_SECONDS); - time_t start_time = time(NULL); - mysql_cond_timedwait (&COND_wsrep_sst, &LOCK_wsrep_sst, &wtime); - time_t end_time = time(NULL); - - if (!sst_complete) - { - total_wtime += difftime(end_time, start_time); - WSREP_DEBUG("Waiting for SST to complete. current seqno: %" PRId64 " waited %f secs.", local_seqno, total_wtime); - service_manager_extend_timeout(WSREP_EXTEND_TIMEOUT_INTERVAL, - "WSREP state transfer ongoing, current seqno: %ld waited %f secs", local_seqno, total_wtime); - } - } - - if (local_seqno >= 0) - { - WSREP_INFO("SST complete, seqno: %lld", (long long) local_seqno); - } - else - { - WSREP_ERROR("SST failed: %d (%s)", - int(-local_seqno), strerror(-local_seqno)); - } - - mysql_mutex_unlock (&LOCK_wsrep_sst); - - return (local_seqno >= 0); -} - // Signal end of SST -void wsrep_sst_complete (const wsrep_uuid_t* sst_uuid, - wsrep_seqno_t sst_seqno, - bool needed) +static void wsrep_sst_complete (THD* thd, + int const rcode) { - if (mysql_mutex_lock (&LOCK_wsrep_sst)) abort(); - if (!sst_complete) - { - sst_complete = true; - sst_needed = needed; - local_uuid = *sst_uuid; - local_seqno = sst_seqno; - mysql_cond_signal (&COND_wsrep_sst); - } - else - { - /* This can happen when called from wsrep_synced_cb(). - At the moment there is no way to check there - if main thread is still waiting for signal, - so wsrep_sst_complete() is called from there - each time wsrep_ready changes from FALSE -> TRUE. - */ - WSREP_DEBUG("Nobody is waiting for SST."); - } - mysql_mutex_unlock (&LOCK_wsrep_sst); + Wsrep_client_service client_service(thd, thd->wsrep_cs()); + Wsrep_server_state::instance().sst_received(client_service, rcode); } -/* + /* If wsrep provider is loaded, inform that the new state snapshot has been received. Also update the local checkpoint. - @param wsrep [IN] wsrep handle + @param thd [IN] @param uuid [IN] Initial state UUID @param seqno [IN] Initial state sequence number @param state [IN] Always NULL, also ignored by wsrep provider (?) @param state_len [IN] Always 0, also ignored by wsrep provider (?) - @param implicit [IN] Whether invoked implicitly due to SST - (true) or explicitly because if change - in wsrep_start_position by user (false). - @return false Success - true Error - */ -bool wsrep_sst_received (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) +void wsrep_sst_received (THD* thd, + const wsrep_uuid_t& uuid, + wsrep_seqno_t const seqno, + const void* const state, + size_t const state_len) { /* To keep track of whether the local uuid:seqno should be updated. Also, note @@ -300,81 +219,40 @@ 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; - } - - if (memcmp(&local_uuid, &uuid, sizeof(wsrep_uuid_t)) || - local_seqno < seqno || seqno < 0) - { - 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. + TODO: Handle backwards compatibility. WSREP API v25 does not have + wsrep schema. */ - if (implicit) - { - WSREP_WARN("Can't continue."); - unireg_abort(1); - } - else - { - return true; + /* + 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. + */ + wsrep::gtid const sst_gtid(wsrep::id(uuid.data, sizeof(uuid.data)), + wsrep::seqno(seqno)); + + if (!wsrep_before_SE()) { + wsrep_set_SE_checkpoint(wsrep::gtid::undefined()); + wsrep_set_SE_checkpoint(sst_gtid); } - } + wsrep_verify_SE_checkpoint(uuid, seqno); -#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) - { - return true; + /* + Both wsrep_init_SR() and wsrep_recover_view() may use + wsrep thread pool. Restore original thd context before returning. + */ + if (thd) { + thd->store_globals(); + } + else { + my_pthread_setspecific_ptr(THR_THD, NULL); } - } - // Now is the good time to update the local state and checkpoint. - if (do_update) - { - if (wsrep_set_SE_checkpoint(uuid, seqno)) + if (WSREP_ON) { - return true; + int const rcode(seqno < 0 ? seqno : 0); + wsrep_sst_complete(thd,rcode); } - - local_uuid= uuid; - local_seqno= seqno; - } - - return false; -} - -// Let applier threads to continue -bool wsrep_sst_continue () -{ - if (sst_needed) - { - WSREP_INFO("Signalling provider to continue."); - return wsrep_sst_received (wsrep, local_uuid, local_seqno, NULL, 0, true); - } - return false; } struct sst_thread_arg @@ -404,11 +282,11 @@ struct sst_thread_arg static int sst_scan_uuid_seqno (const char* str, wsrep_uuid_t* uuid, wsrep_seqno_t* seqno) { - int offt = wsrep_uuid_scan (str, strlen(str), uuid); + int offt= wsrep_uuid_scan (str, strlen(str), uuid); errno= 0; /* Reset the errno */ if (offt > 0 && strlen(str) > (unsigned int)offt && ':' == str[offt]) { - *seqno = strtoll (str + offt + 1, NULL, 10); + *seqno= strtoll (str + offt + 1, NULL, 10); if (*seqno != LLONG_MAX || errno != ERANGE) { return 0; @@ -416,7 +294,7 @@ static int sst_scan_uuid_seqno (const char* str, } WSREP_ERROR("Failed to parse uuid:seqno pair: '%s'", str); - return EINVAL; + return -EINVAL; } // get rid of trailing \n @@ -426,8 +304,8 @@ static char* my_fgets (char* buf, size_t buf_len, FILE* stream) if (ret) { - size_t len = strlen(ret); - if (len > 0 && ret[len - 1] == '\n') ret[len - 1] = '\0'; + size_t len= strlen(ret); + if (len > 0 && ret[len - 1] == '\n') ret[len - 1]= '\0'; } return ret; @@ -482,9 +360,10 @@ static void* sst_joiner_thread (void* a) int err= 1; { - const char magic[] = "ready"; - const size_t magic_len = sizeof(magic) - 1; - const size_t out_len = 512; + THD* thd; + const char magic[]= "ready"; + const size_t magic_len= sizeof(magic) - 1; + const size_t out_len= 512; char out[out_len]; WSREP_INFO("Running: '%s'", arg->cmd); @@ -501,29 +380,31 @@ static void* sst_joiner_thread (void* a) WSREP_ERROR("Failed to read '%s <addr>' from: %s\n\tRead: '%s'", magic, arg->cmd, tmp); proc.wait(); - if (proc.error()) err = proc.error(); + if (proc.error()) err= proc.error(); } else { - err = 0; + err= 0; } } else { - err = proc.error(); + err= proc.error(); WSREP_ERROR("Failed to execute: %s : %d (%s)", arg->cmd, err, strerror(err)); } - // signal sst_prepare thread with ret code, - // it will go on sending SST request + /* + signal sst_prepare thread with ret code, + it will go on sending SST request + */ mysql_mutex_lock (&arg->lock); if (!err) { - arg->ret_str = strdup (out + magic_len + 1); - if (!arg->ret_str) err = ENOMEM; + arg->ret_str= strdup (out + magic_len + 1); + if (!arg->ret_str) err= ENOMEM; } - arg->err = -err; + arg->err= -err; mysql_cond_signal (&arg->cond); mysql_mutex_unlock (&arg->lock); //! @note arg is unusable after that. @@ -531,11 +412,11 @@ static void* sst_joiner_thread (void* a) * initializer thread to ensure single thread of * shutdown. */ - wsrep_uuid_t ret_uuid = WSREP_UUID_UNDEFINED; - wsrep_seqno_t ret_seqno = WSREP_SEQNO_UNDEFINED; + wsrep_uuid_t ret_uuid = WSREP_UUID_UNDEFINED; + wsrep_seqno_t ret_seqno= WSREP_SEQNO_UNDEFINED; // in case of successfull receiver start, wait for SST completion/end - char* tmp = my_fgets (out, out_len, proc.pipe()); + char* tmp= my_fgets (out, out_len, proc.pipe()); proc.wait(); err= EINVAL; @@ -544,7 +425,7 @@ static void* sst_joiner_thread (void* a) { WSREP_ERROR("Failed to read uuid:seqno and wsrep_gtid_domain_id from " "joiner script."); - if (proc.error()) err = proc.error(); + if (proc.error()) err= proc.error(); } else { @@ -552,7 +433,14 @@ static void* sst_joiner_thread (void* a) const char *pos= strchr(out, ' '); if (!pos) { - // There is no wsrep_gtid_domain_id (some older version SST script?). + + if (wsrep_gtid_mode) + { + // There is no wsrep_gtid_domain_id (some older version SST script?). + WSREP_WARN("Did not find domain ID from SST script output '%s'. " + "Domain ID must be set manually to keep binlog consistent", + out); + } err= sst_scan_uuid_seqno (out, &ret_uuid, &ret_seqno); } else { @@ -588,14 +476,59 @@ static void* sst_joiner_thread (void* a) err: + wsrep::gtid ret_gtid; + if (err) { - ret_uuid= WSREP_UUID_UNDEFINED; - ret_seqno= -err; + ret_gtid= wsrep::gtid::undefined(); + } + else + { + ret_gtid= wsrep::gtid(wsrep::id(ret_uuid.data, sizeof(ret_uuid.data)), + wsrep::seqno(ret_seqno)); } - // Tell initializer thread that SST is complete - wsrep_sst_complete (&ret_uuid, ret_seqno, true); + /* + Tell initializer thread that SST is complete + For that initialize a THD + */ + if (my_thread_init()) + { + WSREP_ERROR("my_thread_init() failed, can't signal end of SST. " + "Aborting."); + unireg_abort(1); + } + + thd= new THD(next_thread_id()); + + if (!thd) + { + WSREP_ERROR("Failed to allocate THD to restore view from local state, " + "can't signal end of SST. Aborting."); + unireg_abort(1); + } + + thd->thread_stack= (char*) &thd; + thd->security_ctx->skip_grants(); + thd->system_thread= SYSTEM_THREAD_GENERIC; + thd->real_id= pthread_self(); + + thd->store_globals(); + + /* */ + thd->variables.wsrep_on = 0; + /* No binlogging */ + thd->variables.sql_log_bin = 0; + thd->variables.option_bits &= ~OPTION_BIN_LOG; + /* No general log */ + thd->variables.option_bits |= OPTION_LOG_OFF; + /* Read committed isolation to avoid gap locking */ + thd->variables.tx_isolation= ISO_READ_COMMITTED; + + wsrep_sst_complete (thd, -err); + + delete thd; + my_thread_end(); } return NULL; @@ -694,7 +627,7 @@ static ssize_t sst_prepare_other (const char* method, " %s " WSREP_SST_OPT_PARENT " '%d'" " %s '%s'" - " %s '%s'", + " %s '%s'", method, addr_in, mysql_real_data_home, wsrep_defaults_file, (int)getpid(), binlog_opt, binlog_opt_val, @@ -734,7 +667,7 @@ static ssize_t sst_prepare_other (const char* method, pthread_t tmp; sst_thread_arg arg(cmd_str(), env()); mysql_mutex_lock (&arg.lock); - ret = pthread_create (&tmp, NULL, sst_joiner_thread, &arg); + ret= pthread_create (&tmp, NULL, sst_joiner_thread, &arg); if (ret) { WSREP_ERROR("sst_prepare_other(): pthread_create() failed: %d (%s)", @@ -746,11 +679,11 @@ static ssize_t sst_prepare_other (const char* method, *addr_out= arg.ret_str; if (!arg.err) - ret = strlen(*addr_out); + ret= strlen(*addr_out); else { assert (arg.err < 0); - ret = arg.err; + ret= arg.err; } pthread_detach (tmp); @@ -764,12 +697,12 @@ extern uint mysqld_port; static ssize_t sst_prepare_mysqldump (const char* addr_in, const char** addr_out) { - ssize_t ret = strlen (addr_in); + ssize_t ret= strlen (addr_in); if (!strrchr(addr_in, ':')) { - ssize_t s = ret + 7; - char* tmp = (char*) malloc (s); + ssize_t s= ret + 7; + char* tmp= (char*) malloc (s); if (tmp) { @@ -780,7 +713,7 @@ static ssize_t sst_prepare_mysqldump (const char* addr_in, *addr_out= tmp; return ret; } - if (ret > 0) /* buffer too short */ ret = -EMSGSIZE; + if (ret > 0) /* buffer too short */ ret= -EMSGSIZE; free (tmp); } else { @@ -797,32 +730,22 @@ static ssize_t sst_prepare_mysqldump (const char* addr_in, return ret; } -static bool SE_initialized = false; - -ssize_t wsrep_sst_prepare (void** msg) +std::string wsrep_sst_prepare() { + const ssize_t ip_max= 256; + char ip_buf[ip_max]; const char* addr_in= NULL; const char* addr_out= NULL; const char* method; if (!strcmp(wsrep_sst_method, WSREP_SST_SKIP)) { - ssize_t ret = strlen(WSREP_STATE_TRANSFER_TRIVIAL) + 1; - *msg = strdup(WSREP_STATE_TRANSFER_TRIVIAL); - if (!msg) - { - WSREP_ERROR("Could not allocate %zd bytes for state request", ret); - unireg_abort(1); - } - return ret; + return WSREP_STATE_TRANSFER_TRIVIAL; } /* Figure out SST receive address. Common for all SST methods. */ - char ip_buf[256]; - const ssize_t ip_max= sizeof(ip_buf); - // Attempt 1: wsrep_sst_receive_address if (wsrep_sst_receive_address && strcmp (wsrep_sst_receive_address, WSREP_SST_ADDRESS_AUTO)) @@ -839,7 +762,7 @@ ssize_t wsrep_sst_prepare (void** msg) { WSREP_ERROR("Could not parse wsrep_node_address : %s", wsrep_node_address); - unireg_abort(1); + throw wsrep::runtime_error("Failed to prepare for SST. Unrecoverable"); } memcpy(ip_buf, addr.get_address(), addr.get_address_len()); addr_in= ip_buf; @@ -857,7 +780,7 @@ ssize_t wsrep_sst_prepare (void** msg) { WSREP_ERROR("Failed to guess address to accept state transfer. " "wsrep_sst_receive_address must be set manually."); - unireg_abort(1); + throw wsrep::runtime_error("Could not prepare state transfer request"); } } @@ -866,12 +789,16 @@ ssize_t wsrep_sst_prepare (void** msg) if (!strcmp(method, WSREP_SST_MYSQLDUMP)) { addr_len= sst_prepare_mysqldump (addr_in, &addr_out); - if (addr_len < 0) unireg_abort(1); + if (addr_len < 0) + { + throw wsrep::runtime_error("Could not prepare mysqldimp address"); + } } else { /*! A heuristic workaround until we learn how to stop and start engines */ - if (SE_initialized) + if (Wsrep_server_state::instance().is_initialized() && + Wsrep_server_state::instance().state() == Wsrep_server_state::s_joiner) { if (!strcmp(method, WSREP_SST_XTRABACKUP) || !strcmp(method, WSREP_SST_XTRABACKUPV2)) @@ -890,8 +817,7 @@ ssize_t wsrep_sst_prepare (void** msg) "if other means of state transfer are unavailable. " "In that case you will need to restart the server.", method); - *msg = 0; - return 0; + return ""; } addr_len = sst_prepare_other (method, sst_auth_real, @@ -900,37 +826,28 @@ ssize_t wsrep_sst_prepare (void** msg) { WSREP_ERROR("Failed to prepare for '%s' SST. Unrecoverable.", method); - unireg_abort(1); + throw wsrep::runtime_error("Failed to prepare for SST. Unrecoverable"); } } - size_t const method_len(strlen(method)); - size_t const msg_len (method_len + addr_len + 2 /* + auth_len + 1*/); + std::string ret; + ret += method; + ret.push_back('\0'); + ret += addr_out; - *msg = malloc (msg_len); - if (NULL != *msg) { - char* const method_ptr(reinterpret_cast<char*>(*msg)); - strcpy (method_ptr, method); - char* const addr_ptr(method_ptr + method_len + 1); - strcpy (addr_ptr, addr_out); - - WSREP_INFO ("Prepared SST request: %s|%s", method_ptr, addr_ptr); - } - else { - WSREP_ERROR("Failed to allocate SST request of size %zu. Can't continue.", - msg_len); - unireg_abort(1); - } + const char* method_ptr(ret.data()); + const char* addr_ptr(ret.data() + strlen(method_ptr) + 1); + WSREP_INFO ("Prepared SST request: %s|%s", method_ptr, addr_ptr); if (addr_out != addr_in) /* malloc'ed */ free ((char*)addr_out); - return msg_len; + return ret; } // helper method for donors static int sst_run_shell (const char* cmd_str, char** env, int max_tries) { - int ret = 0; + int ret= 0; for (int tries=1; tries <= max_tries; tries++) { @@ -941,7 +858,7 @@ static int sst_run_shell (const char* cmd_str, char** env, int max_tries) proc.wait(); } - if ((ret = proc.error())) + if ((ret= proc.error())) { WSREP_ERROR("Try %d/%d: '%s' failed: %d (%s)", tries, max_tries, proc.cmd(), ret, strerror(ret)); @@ -959,15 +876,12 @@ static int sst_run_shell (const char* cmd_str, char** env, int max_tries) static void sst_reject_queries(my_bool close_conn) { - wsrep_ready_set (FALSE); // this will be resotred when donor becomes synced - WSREP_INFO("Rejecting client queries for the duration of SST."); - if (TRUE == close_conn) wsrep_close_client_connections(FALSE); + WSREP_INFO("Rejecting client queries for the duration of SST."); + if (TRUE == close_conn) wsrep_close_client_connections(FALSE); } static int sst_donate_mysqldump (const char* addr, - const wsrep_uuid_t* uuid, - const char* uuid_str, - wsrep_seqno_t seqno, + const wsrep::gtid& gtid, bool bypass, char** env) // carries auth info { @@ -990,23 +904,31 @@ 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(); + std::ostringstream uuid_oss; + uuid_oss << gtid.id(); int ret= snprintf (cmd_str(), cmd_len, "wsrep_sst_mysqldump " WSREP_SST_OPT_ADDR " '%s' " - WSREP_SST_OPT_PORT " '%d' " + WSREP_SST_OPT_PORT " '%u' " WSREP_SST_OPT_LPORT " '%u' " WSREP_SST_OPT_SOCKET " '%s' " " %s " WSREP_SST_OPT_GTID " '%s:%lld' " WSREP_SST_OPT_GTID_DOMAIN_ID " '%d'" "%s", - addr, port, mysqld_port, mysqld_unix_port, - wsrep_defaults_file, uuid_str, - (long long)seqno, wsrep_gtid_domain_id, + addr, port, mysqld_port, mysqld_unix_port, + wsrep_defaults_file, + uuid_oss.str().c_str(), gtid.seqno().get(), + wsrep_gtid_domain_id, bypass ? " " WSREP_SST_OPT_BYPASS : ""); if (ret < 0 || ret >= cmd_len) @@ -1019,16 +941,17 @@ static int sst_donate_mysqldump (const char* addr, ret= sst_run_shell (cmd_str(), env, 3); - wsrep_gtid_t const state_id = { *uuid, (ret ? WSREP_SEQNO_UNDEFINED : seqno)}; - - wsrep->sst_sent (wsrep, &state_id, ret); + wsrep::gtid sst_sent_gtid(ret == 0 ? + gtid : + wsrep::gtid(gtid.id(), + wsrep::seqno::undefined())); + Wsrep_server_state::instance().sst_sent(sst_sent_gtid, ret); return ret; } wsrep_seqno_t wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; - /* Create a file under data directory. */ @@ -1077,7 +1000,6 @@ static int sst_create_file(const char *name, const char *content) return err; } - static int run_sql_command(THD *thd, const char *query) { thd->set_query((char *)query, strlen(query)); @@ -1123,9 +1045,9 @@ static int sst_flush_tables(THD* thd) { /* 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; + thd->variables.character_set_client= &my_charset_latin1; WSREP_WARN("For SST temporally setting character set to : %s", - my_charset_latin1.csname); + my_charset_latin1.csname); } if (run_sql_command(thd, "FLUSH TABLES WITH READ LOCK")) @@ -1146,7 +1068,7 @@ static int sst_flush_tables(THD* thd) } } - thd->variables.character_set_client = current_charset; + thd->variables.character_set_client= current_charset; if (err) { @@ -1164,7 +1086,6 @@ static int sst_flush_tables(THD* thd) else { WSREP_INFO("Tables flushed."); - /* Tables have been flushed. Create a file with cluster state ID and wsrep_gtid_domain_id. @@ -1173,6 +1094,41 @@ static int sst_flush_tables(THD* thd) snprintf(content, sizeof(content), "%s:%lld %d\n", wsrep_cluster_state_uuid, (long long)wsrep_locked_seqno, wsrep_gtid_domain_id); err= sst_create_file(flush_success, content); + + const char base_name[]= "tables_flushed"; + ssize_t const full_len= strlen(mysql_real_data_home) + strlen(base_name)+2; + char *real_name= (char*) malloc(full_len); + sprintf(real_name, "%s/%s", mysql_real_data_home, base_name); + char *tmp_name= (char*) malloc(full_len + 4); + sprintf(tmp_name, "%s.tmp", real_name); + + FILE* file= fopen(tmp_name, "w+"); + if (0 == file) + { + err= errno; + WSREP_ERROR("Failed to open '%s': %d (%s)", tmp_name, err,strerror(err)); + } + else + { + Wsrep_server_state& server_state= Wsrep_server_state::instance(); + std::ostringstream uuid_oss; + + uuid_oss << server_state.current_view().state_id().id(); + + fprintf(file, "%s:%lld %u\n", + uuid_oss.str().c_str(), server_state.pause_seqno().get(), + wsrep_gtid_domain_id); + fsync(fileno(file)); + fclose(file); + if (rename(tmp_name, real_name) == -1) + { + err= errno; + WSREP_ERROR("Failed to rename '%s' to '%s': %d (%s)", + tmp_name, real_name, err,strerror(err)); + } + } + free(real_name); + free(tmp_name); } return err; @@ -1181,19 +1137,19 @@ static int sst_flush_tables(THD* thd) static void sst_disallow_writes (THD* thd, bool yes) { - char query_str[64] = { 0, }; - ssize_t const query_max = sizeof(query_str) - 1; + char query_str[64]= { 0, }; + ssize_t const query_max= sizeof(query_str) - 1; CHARSET_INFO *current_charset; - current_charset = thd->variables.character_set_client; + 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; + thd->variables.character_set_client= &my_charset_latin1; WSREP_WARN("For SST temporally setting character set to : %s", - my_charset_latin1.csname); + my_charset_latin1.csname); } snprintf (query_str, query_max, "SET GLOBAL innodb_disallow_writes=%d", @@ -1203,7 +1159,7 @@ static void sst_disallow_writes (THD* thd, bool yes) { WSREP_ERROR("Failed to disallow InnoDB writes"); } - thd->variables.character_set_client = current_charset; + thd->variables.character_set_client= current_charset; } static void* sst_donor_thread (void* a) @@ -1226,11 +1182,11 @@ static void* sst_donor_thread (void* a) // operate with wsrep_ready == OFF wsp::process proc(arg->cmd, "r", arg->env); - err= proc.error(); + err= -proc.error(); /* Inform server about SST script startup and release TO isolation */ mysql_mutex_lock (&arg->lock); - arg->err = -err; + arg->err= -err; mysql_cond_signal (&arg->cond); mysql_mutex_unlock (&arg->lock); //! @note arg is unusable after that. @@ -1289,6 +1245,7 @@ wait_signal: else { WSREP_WARN("Received unknown signal: '%s'", out); + proc.wait(); } } else @@ -1296,7 +1253,7 @@ wait_signal: WSREP_ERROR("Failed to read from: %s", proc.cmd()); proc.wait(); } - if (!err && proc.error()) err= proc.error(); + if (!err && proc.error()) err= -proc.error(); } else { @@ -1315,24 +1272,20 @@ wait_signal: thd.ptr->global_read_lock.unlock_global_read_lock(thd.ptr); } - // signal to donor that SST is over - struct wsrep_gtid const state_id = { - ret_uuid, err ? WSREP_SEQNO_UNDEFINED : ret_seqno - }; - wsrep->sst_sent (wsrep, &state_id, -err); + wsrep::gtid gtid(wsrep::id(ret_uuid.data, sizeof(ret_uuid.data)), + wsrep::seqno(err ? wsrep::seqno::undefined() : + wsrep::seqno(ret_seqno))); + Wsrep_server_state::instance().sst_sent(gtid, err); proc.wait(); return NULL; } - - -static int sst_donate_other (const char* method, - const char* addr, - const char* uuid, - wsrep_seqno_t seqno, - bool bypass, - char** env) // carries auth info +static int sst_donate_other (const char* method, + const char* addr, + const wsrep::gtid& gtid, + bool bypass, + char** env) // carries auth info { int const cmd_len= 4096; wsp::string cmd_str(cmd_len); @@ -1357,6 +1310,8 @@ static int sst_donate_other (const char* method, make_wsrep_defaults_file(); + std::ostringstream uuid_oss; + uuid_oss << gtid.id(); ret= snprintf (cmd_str(), cmd_len, "wsrep_sst_%s " WSREP_SST_OPT_ROLE " 'donor' " @@ -1371,7 +1326,7 @@ static int sst_donate_other (const char* method, method, addr, mysqld_unix_port, mysql_real_data_home, wsrep_defaults_file, binlog_opt, binlog_opt_val, - uuid, (long long) seqno, wsrep_gtid_domain_id, + uuid_oss.str().c_str(), gtid.seqno().get(), wsrep_gtid_domain_id, bypass ? " " WSREP_SST_OPT_BYPASS : ""); my_free(binlog_opt_val); @@ -1386,7 +1341,7 @@ static int sst_donate_other (const char* method, pthread_t tmp; sst_thread_arg arg(cmd_str(), env); mysql_mutex_lock (&arg.lock); - ret = pthread_create (&tmp, NULL, sst_donor_thread, &arg); + ret= pthread_create (&tmp, NULL, sst_donor_thread, &arg); if (ret) { WSREP_ERROR("sst_donate_other(): pthread_create() failed: %d (%s)", @@ -1399,23 +1354,18 @@ 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) +int wsrep_sst_donate(const std::string& msg, + const wsrep::gtid& current_gtid, + const bool 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); + wsrep_config_state->set(wsrep::server_state::s_donor); - const char* method = (char*)msg; - size_t method_len = strlen (method); - const char* data = method + method_len + 1; - - char uuid_str[37]; - wsrep_uuid_print (¤t_gtid->uuid, uuid_str, sizeof(uuid_str)); + const char* method= msg.data(); + size_t method_len= strlen (method); + const char* data= method + method_len + 1; wsp::env env(NULL); if (env.error()) @@ -1443,54 +1393,13 @@ wsrep_cb_status_t wsrep_sst_donate_cb (void* app_ctx, void* recv_ctx, if (!strcmp (WSREP_SST_MYSQLDUMP, method)) { - ret = sst_donate_mysqldump(data, ¤t_gtid->uuid, uuid_str, - current_gtid->seqno, bypass, env()); + ret= sst_donate_mysqldump(data, current_gtid, bypass, env()); } else { - ret = sst_donate_other(method, data, uuid_str, - current_gtid->seqno, bypass, env()); + ret= sst_donate_other(method, data, current_gtid, bypass, env()); } - return (ret >= 0 ? WSREP_CB_SUCCESS : WSREP_CB_FAILURE); -} - -void wsrep_SE_init_grab() -{ - if (mysql_mutex_lock (&LOCK_wsrep_sst_init)) abort(); -} - -void wsrep_SE_init_wait() -{ - double total_wtime=0; - - while (SE_initialized == false) - { - struct timespec wtime; - set_timespec(wtime, WSREP_TIMEDWAIT_SECONDS); - time_t start_time = time(NULL); - mysql_cond_timedwait (&COND_wsrep_sst_init, &LOCK_wsrep_sst_init, &wtime); - time_t end_time = time(NULL); - - if (!SE_initialized) - { - total_wtime += difftime(end_time, start_time); - WSREP_DEBUG("Waiting for SST to complete. current seqno: %" PRId64 " waited %f secs.", local_seqno, total_wtime); - service_manager_extend_timeout(WSREP_EXTEND_TIMEOUT_INTERVAL, - "WSREP state transfer ongoing, current seqno: %ld waited %f secs", local_seqno, total_wtime); - } - } - - mysql_mutex_unlock (&LOCK_wsrep_sst_init); -} - -void wsrep_SE_init_done() -{ - mysql_cond_signal (&COND_wsrep_sst_init); - mysql_mutex_unlock (&LOCK_wsrep_sst_init); -} - -void wsrep_SE_initialized() -{ - SE_initialized = true; + return (ret >= 0 ? 0 : 1); } + diff --git a/sql/wsrep_sst.h b/sql/wsrep_sst.h index 29724a00797..46059a7f436 100644 --- a/sql/wsrep_sst.h +++ b/sql/wsrep_sst.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2013 Codership Oy <info@codership.com> +/* Copyright (C) 2013-2018 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 @@ -13,14 +13,14 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include <my_config.h> - #ifndef WSREP_SST_H #define WSREP_SST_H -#ifdef WITH_WSREP +#include <my_config.h> -#include <mysql.h> // my_bool +#include "wsrep/gtid.hpp" +#include <my_global.h> +#include <string> #define WSREP_SST_OPT_ROLE "--role" #define WSREP_SST_OPT_ADDR "--address" @@ -77,11 +77,29 @@ extern void wsrep_SE_init_wait(); /*! wait for SE init to complete */ extern void wsrep_SE_init_done(); /*! signal that SE init is complte */ extern void wsrep_SE_initialized(); /*! mark SE initialization complete */ +/** + Return a string containing the state transfer request string. + Note that the string may contain a '\0' in the middle. +*/ +std::string wsrep_sst_prepare(); + +/** + Donate a SST. + + @param request SST request string received from the joiner. Note that + the string may contain a '\0' in the middle. + @param gtid Current position of the donor + @param bypass If true, full SST is not needed. Joiner needs to be + notified that it can continue starting from gtid. + */ +int wsrep_sst_donate(const std::string& request, + const wsrep::gtid& gtid, + bool bypass); + #else #define wsrep_SE_initialized() do { } while(0) #define wsrep_SE_init_grab() do { } while(0) #define wsrep_SE_init_done() do { } while(0) #define wsrep_sst_continue() (0) -#endif /* WITH_WSREP */ #endif /* WSREP_SST_H */ diff --git a/sql/wsrep_storage_service.cc b/sql/wsrep_storage_service.cc new file mode 100644 index 00000000000..5a15f22ab57 --- /dev/null +++ b/sql/wsrep_storage_service.cc @@ -0,0 +1,238 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "my_global.h" +#include "wsrep_storage_service.h" +#include "wsrep_trans_observer.h" /* wsrep_open() */ +#include "wsrep_schema.h" +#include "wsrep_binlog.h" + +#include "sql_class.h" +#include "mysqld.h" /* next_query_id() */ +#include "slave.h" /* opt_log_slave_updates() */ +#include "transaction.h" /* trans_commit(), trans_rollback() */ + +/* + Temporarily enable wsrep on thd + */ +class Wsrep_on +{ +public: + Wsrep_on(THD* thd) + : m_thd(thd) + , m_wsrep_on(thd->variables.wsrep_on) + { + thd->variables.wsrep_on= TRUE; + } + ~Wsrep_on() + { + m_thd->variables.wsrep_on= m_wsrep_on; + } +private: + THD* m_thd; + my_bool m_wsrep_on; +}; + +Wsrep_storage_service::Wsrep_storage_service(THD* thd) + : wsrep::storage_service() + , wsrep::high_priority_context(thd->wsrep_cs()) + , m_thd(thd) +{ + thd->security_ctx->skip_grants(); + thd->system_thread= SYSTEM_THREAD_SLAVE_SQL; + + /* No binlogging */ + + /* No general log */ + thd->variables.option_bits |= OPTION_LOG_OFF; + + /* Read committed isolation to avoid gap locking */ + thd->variables.tx_isolation = ISO_READ_COMMITTED; + + /* Keep wsrep on to enter commit ordering hooks */ + thd->variables.wsrep_on= 1; + thd->wsrep_skip_locking= true; + + wsrep_open(thd); + wsrep_before_command(thd); +} + +Wsrep_storage_service::~Wsrep_storage_service() +{ + wsrep_after_command_ignore_result(m_thd); + wsrep_close(m_thd); + m_thd->wsrep_skip_locking= false; +} + +int Wsrep_storage_service::start_transaction(const wsrep::ws_handle& ws_handle) +{ + DBUG_ENTER("Wsrep_storage_service::start_transaction"); + DBUG_ASSERT(m_thd == current_thd); + DBUG_PRINT("info", ("Wsrep_storage_service::start_transcation(%llu, %p)", + m_thd->thread_id, m_thd)); + m_thd->set_wsrep_next_trx_id(ws_handle.transaction_id().get()); + DBUG_RETURN(m_thd->wsrep_cs().start_transaction( + wsrep::transaction_id(m_thd->wsrep_next_trx_id())) || + trans_begin(m_thd, MYSQL_START_TRANS_OPT_READ_WRITE)); +} + +void Wsrep_storage_service::adopt_transaction(const wsrep::transaction& transaction) +{ + DBUG_ENTER("Wsrep_Storage_server::adopt_transaction"); + DBUG_ASSERT(m_thd == current_thd); + m_thd->wsrep_cs().adopt_transaction(transaction); + trans_begin(m_thd, MYSQL_START_TRANS_OPT_READ_WRITE); + DBUG_VOID_RETURN; +} + +int Wsrep_storage_service::append_fragment(const wsrep::id& server_id, + wsrep::transaction_id transaction_id, + int flags, + const wsrep::const_buffer& data) +{ + DBUG_ENTER("Wsrep_storage_service::append_fragment"); + DBUG_ASSERT(m_thd == current_thd); + DBUG_PRINT("info", ("Wsrep_storage_service::append_fragment(%llu, %p)", + m_thd->thread_id, m_thd)); + int ret= wsrep_schema->append_fragment(m_thd, + server_id, + transaction_id, + wsrep::seqno(-1), + flags, + data); + DBUG_RETURN(ret); +} + +int Wsrep_storage_service::update_fragment_meta(const wsrep::ws_meta& ws_meta) +{ + DBUG_ENTER("Wsrep_storage_service::update_fragment_meta"); + DBUG_ASSERT(m_thd == current_thd); + DBUG_PRINT("info", ("Wsrep_storage_service::update_fragment_meta(%llu, %p)", + m_thd->thread_id, m_thd)); + int ret= wsrep_schema->update_fragment_meta(m_thd, ws_meta); + DBUG_RETURN(ret); +} + +int Wsrep_storage_service::remove_fragments() +{ + DBUG_ENTER("Wsrep_storage_service::remove_fragments"); + DBUG_ASSERT(m_thd == current_thd); + + int ret= wsrep_schema->remove_fragments(m_thd, + m_thd->wsrep_trx().server_id(), + m_thd->wsrep_trx().id(), + m_thd->wsrep_sr().fragments()); + DBUG_RETURN(ret); +} + +int Wsrep_storage_service::commit(const wsrep::ws_handle& ws_handle, + const wsrep::ws_meta& ws_meta) +{ + DBUG_ENTER("Wsrep_storage_service::commit"); + DBUG_ASSERT(m_thd == current_thd); + DBUG_PRINT("info", ("Wsrep_storage_service::commit(%llu, %p)", + m_thd->thread_id, m_thd)); + WSREP_DEBUG("Storage service commit: %llu, %lld", + ws_meta.transaction_id().get(), ws_meta.seqno().get()); + int ret= 0; + const bool do_binlog_commit= (opt_log_slave_updates && wsrep_gtid_mode); + const bool is_ordered= !ws_meta.seqno().is_undefined(); + /* + Write skip event into binlog if gtid_mode is on. This is to + maintain gtid continuity. + */ + if (do_binlog_commit && is_ordered) + { + ret= wsrep_write_skip_event(m_thd); + } + + if (!ret && is_ordered) + { + ret= m_thd->wsrep_cs().prepare_for_ordering(ws_handle, + ws_meta, true); + } + + if (!ret) + { + if (!do_binlog_commit && is_ordered) + { + ret= wsrep_before_commit(m_thd, true); + } + ret= ret || trans_commit(m_thd); + if (!do_binlog_commit && is_ordered) + { + if (opt_log_slave_updates) + { + ret= ret || wsrep_ordered_commit(m_thd, true, wsrep_apply_error()); + } + ret= ret || wsrep_after_commit(m_thd, true); + } + } + + if (!is_ordered) + { + /* Wsrep commit was not ordered so it does not go through commit time + hooks and remains active. Roll it back to make cleanup happen + in after_applying() call. */ + m_thd->wsrep_cs().before_rollback(); + m_thd->wsrep_cs().after_rollback(); + } + else if (ret) + { + /* Commit failed, this probably means that the parent SR transaction + was BF aborted. Roll back out of order, the parent + transaction will release commit order after it has rolled back. */ + m_thd->wsrep_cs().prepare_for_ordering(wsrep::ws_handle(), + wsrep::ws_meta(), + false); + trans_rollback(m_thd); + } + m_thd->wsrep_cs().after_applying(); + m_thd->mdl_context.release_transactional_locks(); + DBUG_RETURN(ret); +} + +int Wsrep_storage_service::rollback(const wsrep::ws_handle& ws_handle, + const wsrep::ws_meta& ws_meta) +{ + DBUG_ENTER("Wsrep_storage_service::rollback"); + DBUG_ASSERT(m_thd == current_thd); + DBUG_PRINT("info", ("Wsrep_storage_service::rollback(%llu, %p)", + m_thd->thread_id, m_thd)); + int ret= (m_thd->wsrep_cs().prepare_for_ordering( + ws_handle, ws_meta, false) || + trans_rollback(m_thd)); + m_thd->wsrep_cs().after_applying(); + m_thd->mdl_context.release_transactional_locks(); + DBUG_RETURN(ret); +} + +void Wsrep_storage_service::store_globals() +{ + DBUG_ENTER("Wsrep_storage_service::store_globals"); + DBUG_PRINT("info", ("Wsrep_storage_service::store_globals(%llu, %p)", + m_thd->thread_id, m_thd)); + m_thd->store_globals(); + DBUG_VOID_RETURN; +} + +void Wsrep_storage_service::reset_globals() +{ + DBUG_ENTER("Wsrep_storage_service::reset_globals"); + DBUG_PRINT("info", ("Wsrep_storage_service::reset_globals(%llu, %p)", + m_thd->thread_id, m_thd)); + m_thd->reset_globals(); + DBUG_VOID_RETURN; +} diff --git a/sql/wsrep_storage_service.h b/sql/wsrep_storage_service.h new file mode 100644 index 00000000000..6208300930f --- /dev/null +++ b/sql/wsrep_storage_service.h @@ -0,0 +1,48 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef WSREP_STORAGE_SERVICE_H +#define WSREP_STORAGE_SERVICE_H + +#include "wsrep/storage_service.hpp" +#include "wsrep/client_state.hpp" + +class THD; +class Wsrep_server_service; +class Wsrep_storage_service : + public wsrep::storage_service, + public wsrep::high_priority_context +{ +public: + Wsrep_storage_service(THD*); + ~Wsrep_storage_service(); + int start_transaction(const wsrep::ws_handle&); + void adopt_transaction(const wsrep::transaction&); + int append_fragment(const wsrep::id&, + wsrep::transaction_id, + int flags, + const wsrep::const_buffer&); + int update_fragment_meta(const wsrep::ws_meta&); + int remove_fragments(); + int commit(const wsrep::ws_handle&, const wsrep::ws_meta&); + int rollback(const wsrep::ws_handle&, const wsrep::ws_meta&); + void store_globals(); + void reset_globals(); +private: + friend class Wsrep_server_service; + THD* m_thd; +}; + +#endif /* WSREP_STORAGE_SERVICE_H */ diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index ce6d9688cb3..4f9915fa05f 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -15,412 +15,82 @@ #include "mariadb.h" #include "wsrep_thd.h" +#include "wsrep_trans_observer.h" +#include "wsrep_high_priority_service.h" +#include "wsrep_storage_service.h" #include "transaction.h" #include "rpl_rli.h" #include "log_event.h" #include "sql_parse.h" -//#include "global_threads.h" // LOCK_thread_count, etc. #include "sql_base.h" // close_thread_tables() #include "mysqld.h" // start_wsrep_THD(); - -#include "slave.h" // opt_log_slave_updates -#include "rpl_filter.h" +#include "wsrep_applier.h" // start_wsrep_THD(); +#include "mysql/service_wsrep.h" +#include "debug_sync.h" +#include "slave.h" #include "rpl_rli.h" #include "rpl_mi.h" -#if (__LP64__) -static volatile int64 wsrep_bf_aborts_counter(0); -#define WSREP_ATOMIC_LOAD_LONG my_atomic_load64 -#define WSREP_ATOMIC_ADD_LONG my_atomic_add64 -#else -static volatile int32 wsrep_bf_aborts_counter(0); -#define WSREP_ATOMIC_LOAD_LONG my_atomic_load32 -#define WSREP_ATOMIC_ADD_LONG my_atomic_add32 -#endif +static Wsrep_thd_queue* wsrep_rollback_queue= 0; +static Wsrep_thd_queue* wsrep_post_rollback_queue= 0; +static Atomic_counter<uint64_t> wsrep_bf_aborts_counter; + int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, char *buff, enum enum_var_type scope) { - wsrep_local_bf_aborts = WSREP_ATOMIC_LOAD_LONG(&wsrep_bf_aborts_counter); - var->type = SHOW_LONGLONG; - var->value = (char*)&wsrep_local_bf_aborts; + wsrep_local_bf_aborts= wsrep_bf_aborts_counter; + var->type= SHOW_LONGLONG; + var->value= (char*)&wsrep_local_bf_aborts; return 0; } -/* must have (&thd->LOCK_thd_data) */ -void wsrep_client_rollback(THD *thd) -{ - WSREP_DEBUG("client rollback due to BF abort for (%lld), query: %s", - (longlong) thd->thread_id, thd->query()); - - WSREP_ATOMIC_ADD_LONG(&wsrep_bf_aborts_counter, 1); - - thd->wsrep_conflict_state= ABORTING; - mysql_mutex_unlock(&thd->LOCK_thd_data); - trans_rollback(thd); - - if (thd->locked_tables_mode && thd->lock) - { - WSREP_DEBUG("unlocking tables for BF abort (%lld)", - (longlong) 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); - thd->global_read_lock.unlock_global_read_lock(thd); - } - - /* Release transactional metadata locks. */ - thd->mdl_context.release_transactional_locks(); - - /* release explicit MDL locks */ - thd->mdl_context.release_explicit_locks(); - - if (thd->get_binlog_table_maps()) - { - WSREP_DEBUG("clearing binlog table map for BF abort (%lld)", - (longlong) thd->thread_id); - thd->clear_binlog_table_maps(); - } - mysql_mutex_lock(&thd->LOCK_thd_data); - thd->wsrep_conflict_state= ABORTED; -} - -#define NUMBER_OF_FIELDS_TO_IDENTIFY_COORDINATOR 1 -#define NUMBER_OF_FIELDS_TO_IDENTIFY_WORKER 2 - -static rpl_group_info* wsrep_relay_group_init(const char* log_fname) -{ - Relay_log_info* rli= new Relay_log_info(false); - - if (!rli->relay_log.description_event_for_exec) - { - rli->relay_log.description_event_for_exec= - new Format_description_log_event(4); - } - - static LEX_CSTRING connection_name= { STRING_WITH_LEN("wsrep") }; - - /* - Master_info's constructor initializes rpl_filter by either an already - constructed Rpl_filter object from global 'rpl_filters' list if the - specified connection name is same, or it constructs a new Rpl_filter - object and adds it to rpl_filters. This object is later destructed by - Mater_info's destructor by looking it up based on connection name in - rpl_filters list. - - However, since all Master_info objects created here would share same - connection name ("wsrep"), destruction of any of the existing Master_info - objects (in wsrep_return_from_bf_mode()) would free rpl_filter referenced - by any/all existing Master_info objects. - - In order to avoid that, we have added a check in Master_info's destructor - to not free the "wsrep" rpl_filter. It will eventually be freed by - free_all_rpl_filters() when server terminates. - */ - rli->mi = new Master_info(&connection_name, false); - - struct rpl_group_info *rgi= new rpl_group_info(rli); - rgi->thd= rli->sql_driver_thd= current_thd; - - if ((rgi->deferred_events_collecting= rli->mi->rpl_filter->is_on())) - { - rgi->deferred_events= new Deferred_log_events(rli); - } - - return rgi; -} - -static void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow* shadow) +static void wsrep_replication_process(THD *thd, + void* arg __attribute__((unused))) { - shadow->options = thd->variables.option_bits; - shadow->server_status = thd->server_status; - shadow->wsrep_exec_mode = thd->wsrep_exec_mode; - shadow->vio = thd->net.vio; - - // Disable general logging on applier threads - thd->variables.option_bits |= OPTION_LOG_OFF; - // Enable binlogging if opt_log_slave_updates is set - if (opt_log_slave_updates) - thd->variables.option_bits|= OPTION_BIN_LOG; - else - thd->variables.option_bits&= ~(OPTION_BIN_LOG); + DBUG_ENTER("wsrep_replication_process"); - if (!thd->wsrep_rgi) thd->wsrep_rgi= wsrep_relay_group_init("wsrep_relay"); + Wsrep_applier_service applier_service(thd); /* thd->system_thread_info.rpl_sql_info isn't initialized. */ thd->system_thread_info.rpl_sql_info= new rpl_sql_thread_info(thd->wsrep_rgi->rli->mi->rpl_filter); - thd->wsrep_exec_mode= REPL_RECV; - thd->net.vio= 0; - thd->clear_error(); - - shadow->tx_isolation = thd->variables.tx_isolation; - thd->variables.tx_isolation = ISO_READ_COMMITTED; - thd->tx_isolation = ISO_READ_COMMITTED; - - shadow->db = thd->db.str; - shadow->db_length = thd->db.length; - shadow->user_time = thd->user_time; - shadow->row_count_func= thd->get_row_count_func(); - thd->reset_db(&null_clex_str); -} + WSREP_INFO("Starting applier thread %llu", thd->thread_id); + enum wsrep::provider::status + ret= Wsrep_server_state::get_provider().run_applier(&applier_service); -static 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; - thd->server_status = shadow->server_status; - thd->wsrep_exec_mode = shadow->wsrep_exec_mode; - thd->net.vio = shadow->vio; - thd->variables.tx_isolation = shadow->tx_isolation; - thd->user_time = shadow->user_time; - thd->reset_db(&db); + WSREP_INFO("Applier thread exiting %d", ret); + mysql_mutex_lock(&LOCK_thread_count); + wsrep_close_applier(thd); + mysql_cond_broadcast(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); delete thd->system_thread_info.rpl_sql_info; delete thd->wsrep_rgi->rli->mi; delete thd->wsrep_rgi->rli; - + thd->wsrep_rgi->cleanup_after_session(); delete thd->wsrep_rgi; - thd->wsrep_rgi = NULL; - thd->set_row_count_func(shadow->row_count_func); -} - -void wsrep_replay_transaction(THD *thd) -{ - DBUG_ENTER("wsrep_replay_transaction"); - /* checking if BF trx must be replayed */ - if (thd->wsrep_conflict_state== MUST_REPLAY) { - DBUG_ASSERT(wsrep_thd_trx_seqno(thd)); - if (thd->wsrep_exec_mode!= REPL_RECV) { - if (thd->get_stmt_da()->is_sent()) - { - WSREP_ERROR("replay issue, thd has reported status already"); - } - - - /* - PS reprepare observer should have been removed already. - open_table() will fail if we have dangling observer here. - */ - DBUG_ASSERT(thd->m_reprepare_observer == NULL); - - struct da_shadow - { - enum Diagnostics_area::enum_diagnostics_status status; - ulonglong affected_rows; - ulonglong last_insert_id; - char message[MYSQL_ERRMSG_SIZE]; - }; - struct da_shadow da_status; - da_status.status= thd->get_stmt_da()->status(); - if (da_status.status == Diagnostics_area::DA_OK) - { - da_status.affected_rows= thd->get_stmt_da()->affected_rows(); - da_status.last_insert_id= thd->get_stmt_da()->last_insert_id(); - strmake(da_status.message, - thd->get_stmt_da()->message(), - sizeof(da_status.message)-1); - } - - thd->get_stmt_da()->reset_diagnostics_area(); - - thd->wsrep_conflict_state= REPLAYING; - mysql_mutex_unlock(&thd->LOCK_thd_data); + thd->wsrep_rgi= NULL; - thd->reset_for_next_command(); - thd->reset_killed(); - close_thread_tables(thd); - if (thd->locked_tables_mode && thd->lock) - { - WSREP_DEBUG("releasing table lock for replaying (%lld)", - (longlong) thd->thread_id); - thd->locked_tables_list.unlock_locked_tables(thd); - thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); - } - thd->mdl_context.release_transactional_locks(); - /* - Replaying will call MYSQL_START_STATEMENT when handling - BEGIN Query_log_event so end statement must be called before - replaying. - */ - MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da()); - thd->m_statement_psi= NULL; - thd->m_digest= NULL; - thd_proc_info(thd, "WSREP replaying trx"); - WSREP_DEBUG("replay trx: %s %lld", - thd->query() ? thd->query() : "void", - (long long)wsrep_thd_trx_seqno(thd)); - struct wsrep_thd_shadow shadow; - wsrep_prepare_bf_thd(thd, &shadow); - - /* From trans_begin() */ - thd->variables.option_bits|= OPTION_BEGIN; - thd->server_status|= SERVER_STATUS_IN_TRANS; - - int rcode = wsrep->replay_trx(wsrep, - &thd->wsrep_ws_handle, - (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 ); - - mysql_mutex_lock(&thd->LOCK_thd_data); - - switch (rcode) - { - case WSREP_OK: - thd->wsrep_conflict_state= NO_CONFLICT; - wsrep->post_commit(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()) - { - WSREP_WARN("replay ok, thd has reported status"); - } - else if (thd->get_stmt_da()->is_set()) - { - if (thd->get_stmt_da()->status() != Diagnostics_area::DA_OK && - thd->get_stmt_da()->status() != Diagnostics_area::DA_OK_BULK) - { - WSREP_WARN("replay ok, thd has error status %d", - thd->get_stmt_da()->status()); - } - } - else - { - if (da_status.status == Diagnostics_area::DA_OK) - { - my_ok(thd, - da_status.affected_rows, - da_status.last_insert_id, - da_status.message); - } - else - { - my_ok(thd); - } - } - break; - case WSREP_TRX_FAIL: - if (thd->get_stmt_da()->is_sent()) - { - WSREP_ERROR("replay failed, thd has reported status"); - } - else - { - WSREP_DEBUG("replay failed, rolling back"); - } - thd->wsrep_conflict_state= ABORTED; - wsrep->post_rollback(wsrep, &thd->wsrep_ws_handle); - break; - default: - WSREP_ERROR("trx_replay failed for: %d, schema: %s, query: %s", - rcode, thd->get_db(), - thd->query() ? thd->query() : "void"); - /* 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; - } - - wsrep_cleanup_transaction(thd); - - mysql_mutex_lock(&LOCK_wsrep_replaying); - wsrep_replaying--; - WSREP_DEBUG("replaying decreased: %d, thd: %lld", - wsrep_replaying, (longlong) thd->thread_id); - mysql_cond_broadcast(&COND_wsrep_replaying); - mysql_mutex_unlock(&LOCK_wsrep_replaying); - } - } - DBUG_VOID_RETURN; -} - -static void wsrep_replication_process(THD *thd) -{ - int rcode; - DBUG_ENTER("wsrep_replication_process"); - - struct wsrep_thd_shadow shadow; - wsrep_prepare_bf_thd(thd, &shadow); - - /* From trans_begin() */ - thd->variables.option_bits|= OPTION_BEGIN; - thd->server_status|= SERVER_STATUS_IN_TRANS; - - rcode = wsrep->recv(wsrep, (void *)thd); - DBUG_PRINT("wsrep",("wsrep_repl returned: %d", rcode)); - - WSREP_INFO("applier thread exiting (code:%d)", rcode); - - switch (rcode) { - case WSREP_OK: - case WSREP_NOT_IMPLEMENTED: - case WSREP_CONN_FAIL: - /* provider does not support slave operations / disconnected from group, - * just close applier thread */ - break; - case WSREP_NODE_FAIL: - /* data inconsistency => SST is needed */ - /* Note: we cannot just blindly restart replication here, - * SST might require server restart if storage engines must be - * initialized after SST */ - WSREP_ERROR("node consistency compromised, aborting"); - wsrep_kill_mysql(thd); - break; - case WSREP_WARNING: - case WSREP_TRX_FAIL: - case WSREP_TRX_MISSING: - /* these suggests a bug in provider code */ - WSREP_WARN("bad return from recv() call: %d", rcode); - /* Shut down this node. */ - /* fall through */ - case WSREP_FATAL: - /* Cluster connectivity is lost. - * - * If applier was killed on purpose (KILL_CONNECTION), we - * avoid mysql shutdown. This is because the killer will then handle - * shutdown processing (or replication restarting) - */ - if (thd->killed != KILL_CONNECTION) - { - wsrep_kill_mysql(thd); - } - break; - } - - mysql_mutex_lock(&LOCK_thread_count); - wsrep_close_applier(thd); - mysql_cond_broadcast(&COND_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); if(thd->has_thd_temporary_tables()) { WSREP_WARN("Applier %lld has temporary tables at exit.", thd->thread_id); } - wsrep_return_from_bf_mode(thd, &shadow); 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 @@ -435,244 +105,291 @@ static bool create_wsrep_THD(wsrep_thd_processor_fun processor) void wsrep_create_appliers(long threads) { - if (!wsrep_connected) + /* Dont' start slave threads if wsrep-provider or wsrep-cluster-address + is not set. + */ + if (!WSREP_PROVIDER_EXISTS) + { + return; + } + + if (!wsrep_cluster_address || wsrep_cluster_address[0]== 0) { - /* see wsrep_replication_start() for the logic */ - if (wsrep_cluster_address && strlen(wsrep_cluster_address) && - wsrep_provider && strcasecmp(wsrep_provider, "none")) - { - WSREP_ERROR("Trying to launch slave threads before creating " - "connection at '%s'", wsrep_cluster_address); - assert(0); - } return; } 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; - - while (thd->killed == NOT_KILLED) { - thd_proc_info(thd, "WSREP aborter idle"); - thd->mysys_var->current_mutex= &LOCK_wsrep_rollback; - thd->mysys_var->current_cond= &COND_wsrep_rollback; + THD* thd= NULL; + DBUG_ASSERT(!wsrep_rollback_queue); + wsrep_rollback_queue= new Wsrep_thd_queue(rollbacker); - mysql_cond_wait(&COND_wsrep_rollback,&LOCK_wsrep_rollback); + thd_proc_info(rollbacker, "wsrep aborter idle"); + while ((thd= wsrep_rollback_queue->pop_front()) != NULL) + { + mysql_mutex_lock(&thd->LOCK_thd_data); + wsrep::client_state& cs(thd->wsrep_cs()); + const wsrep::transaction& tx(cs.transaction()); + if (tx.state() == wsrep::transaction::s_aborted) + { + WSREP_DEBUG("rollbacker thd already aborted: %llu state: %d", + (long long)thd->real_id, + tx.state()); - WSREP_DEBUG("WSREP rollback thread wakes for signal"); + mysql_mutex_unlock(&thd->LOCK_thd_data); + continue; + } + mysql_mutex_unlock(&thd->LOCK_thd_data); - mysql_mutex_lock(&thd->mysys_var->mutex); - thd_proc_info(thd, "WSREP aborter active"); - thd->mysys_var->current_mutex= 0; - thd->mysys_var->current_cond= 0; - mysql_mutex_unlock(&thd->mysys_var->mutex); + thd_proc_info(rollbacker, "wsrep aborter active"); - /* check for false alarms */ - if (!wsrep_aborting_thd) + wsrep::transaction_id transaction_id(thd->wsrep_trx().id()); + if (thd->wsrep_trx().is_streaming() && + thd->wsrep_trx().bf_aborted_in_total_order()) { - WSREP_DEBUG("WSREP rollback thread has empty abort queue"); - } - /* process all entries in the queue */ - while (wsrep_aborting_thd) { - THD *aborting; - wsrep_aborting_thd_t next = wsrep_aborting_thd->next; - aborting = wsrep_aborting_thd->aborting_thd; - my_free(wsrep_aborting_thd); - wsrep_aborting_thd= next; - /* - * must release mutex, appliers my want to add more - * aborting thds in our work queue, while we rollback - */ - mysql_mutex_unlock(&LOCK_wsrep_rollback); - - mysql_mutex_lock(&aborting->LOCK_thd_data); - if (aborting->wsrep_conflict_state== ABORTED) + thd->store_globals(); + thd->wsrep_cs().store_globals(); + if (thd->wsrep_cs().mode() == wsrep::client_state::m_high_priority) { - WSREP_DEBUG("WSREP, thd already aborted: %llu state: %d", - (long long)aborting->real_id, - aborting->wsrep_conflict_state); - - mysql_mutex_unlock(&aborting->LOCK_thd_data); - mysql_mutex_lock(&LOCK_wsrep_rollback); - continue; + DBUG_ASSERT(thd->wsrep_applier_service); + thd->wsrep_applier_service->rollback(wsrep::ws_handle(), + wsrep::ws_meta()); + thd->wsrep_applier_service->after_apply(); + /* Will free THD */ + Wsrep_server_state::instance().server_service(). + release_high_priority_service(thd->wsrep_applier_service); } - 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); - - set_current_thd(thd); + else + { + mysql_mutex_lock(&thd->LOCK_thd_data); + /* prepare THD for rollback processing */ + thd->reset_for_next_command(true); + thd->lex->sql_command= SQLCOM_ROLLBACK; + mysql_mutex_unlock(&thd->LOCK_thd_data); + /* Perform a client rollback, restore globals and signal + the victim only when all the resources have been + released */ + thd->wsrep_cs().client_service().bf_rollback(); + thd->reset_globals(); + thd->wsrep_cs().sync_rollback_complete(); + } + } + else if (wsrep_thd_is_applying(thd)) + { + WSREP_DEBUG("rollbacker aborting SR thd: (%lld %llu)", + thd->thread_id, (long long)thd->real_id); + DBUG_ASSERT(thd->wsrep_cs().mode() == Wsrep_client_state::m_high_priority); + /* Must be streaming and must have been removed from the + server state streaming appliers map. */ + DBUG_ASSERT(thd->wsrep_trx().is_streaming()); + DBUG_ASSERT(!Wsrep_server_state::instance().find_streaming_applier( + thd->wsrep_trx().server_id(), + thd->wsrep_trx().id())); + DBUG_ASSERT(thd->wsrep_applier_service); + + /* Fragment removal should happen before rollback to make + the transaction non-observable in SR table after the rollback + completes. For correctness the order does not matter here, + but currently it is mandated by checks in some MTR tests. */ + Wsrep_storage_service* storage_service= + static_cast<Wsrep_storage_service*>( + Wsrep_server_state::instance().server_service().storage_service( + *thd->wsrep_applier_service)); + storage_service->store_globals(); + storage_service->adopt_transaction(thd->wsrep_trx()); + storage_service->remove_fragments(); + storage_service->commit(wsrep::ws_handle(transaction_id, 0), + wsrep::ws_meta()); + Wsrep_server_state::instance().server_service().release_storage_service(storage_service); thd->store_globals(); + thd->wsrep_cs().store_globals(); + thd->wsrep_applier_service->rollback(wsrep::ws_handle(), + wsrep::ws_meta()); + thd->wsrep_applier_service->after_apply(); + /* Will free THD */ + Wsrep_server_state::instance().server_service() + .release_high_priority_service(thd->wsrep_applier_service); - mysql_mutex_lock(&LOCK_wsrep_rollback); } + else + { + if (thd->wsrep_trx().is_streaming()) + { + Wsrep_storage_service* storage_service= + static_cast<Wsrep_storage_service*>( + Wsrep_server_state::instance().server_service(). + storage_service(thd->wsrep_cs().client_service())); + + storage_service->store_globals(); + storage_service->adopt_transaction(thd->wsrep_trx()); + storage_service->remove_fragments(); + storage_service->commit(wsrep::ws_handle(transaction_id, 0), + wsrep::ws_meta()); + Wsrep_server_state::instance().server_service(). + release_storage_service(storage_service); + } + thd->store_globals(); + thd->wsrep_cs().store_globals(); + mysql_mutex_lock(&thd->LOCK_thd_data); + /* prepare THD for rollback processing */ + thd->reset_for_next_command(); + thd->lex->sql_command= SQLCOM_ROLLBACK; + mysql_mutex_unlock(&thd->LOCK_thd_data); + /* Perform a client rollback, restore globals and signal + the victim only when all the resources have been + released */ + thd->wsrep_cs().client_service().bf_rollback(); + thd->reset_globals(); + thd->wsrep_cs().sync_rollback_complete(); + WSREP_DEBUG("rollbacker aborted thd: (%llu %llu)", + thd->thread_id, (long long)thd->real_id); + } + + thd_proc_info(rollbacker, "wsrep aborter idle"); } + + 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; } -void wsrep_create_rollbacker() +static void wsrep_post_rollback_process(THD *post_rollbacker, + void *arg __attribute__((unused))) { - if (wsrep_provider && strcasecmp(wsrep_provider, "none")) - { - /* create rollbacker */ - if (create_wsrep_THD(wsrep_rollback_process)) - WSREP_WARN("Can't create thread to manage wsrep rollback"); - } -} + DBUG_ENTER("wsrep_post_rollback_process"); + THD* thd= NULL; -void wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe) -{ - if (thd_ptr) - { - THD* thd = (THD*)thd_ptr; - thd->wsrep_PA_safe = safe; - } -} + DBUG_ASSERT(!wsrep_post_rollback_queue); + wsrep_post_rollback_queue= new Wsrep_thd_queue(post_rollbacker); -enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd, my_bool sync) -{ - enum wsrep_conflict_state state = NO_CONFLICT; - if (thd) + while ((thd= wsrep_post_rollback_queue->pop_front()) != NULL) { - if (sync) mysql_mutex_lock(&thd->LOCK_thd_data); - - state = thd->wsrep_conflict_state; - if (sync) mysql_mutex_unlock(&thd->LOCK_thd_data); + thd->store_globals(); + wsrep::client_state& cs(thd->wsrep_cs()); + mysql_mutex_lock(&thd->LOCK_thd_data); + DBUG_ASSERT(thd->wsrep_trx().state() == wsrep::transaction::s_aborting); + WSREP_DEBUG("post rollbacker calling post rollback for thd %llu, conf %s", + thd->thread_id, wsrep_thd_transaction_state_str(thd)); + + cs.after_rollback(); + DBUG_ASSERT(thd->wsrep_trx().state() == wsrep::transaction::s_aborted); + mysql_mutex_unlock(&thd->LOCK_thd_data); } - return state; -} -my_bool wsrep_thd_is_wsrep(THD *thd) -{ - my_bool status = FALSE; - if (thd) - { - status = (WSREP(thd) && WSREP_PROVIDER_EXISTS); - } - return status; + 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; } -my_bool wsrep_thd_is_BF(THD *thd, my_bool sync) +void wsrep_create_rollbacker() { - my_bool status = FALSE; - if (thd) + if (wsrep_provider && strcasecmp(wsrep_provider, "none")) { - // THD can be BF only if provider exists - if (wsrep_thd_is_wsrep(thd)) - { - if (sync) - mysql_mutex_lock(&thd->LOCK_thd_data); + Wsrep_thd_args* args= new Wsrep_thd_args(wsrep_rollback_process, 0); - status = ((thd->wsrep_exec_mode == REPL_RECV) || - (thd->wsrep_exec_mode == TOTAL_ORDER)); - if (sync) - mysql_mutex_unlock(&thd->LOCK_thd_data); - } - } - return status; -} + /* create rollbacker */ + if (create_wsrep_THD(args)) + WSREP_WARN("Can't create thread to manage wsrep rollback"); -extern "C" -my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync) -{ - bool status = FALSE; - if (thd_ptr) - { - THD* thd = (THD*)thd_ptr; - if (sync) mysql_mutex_lock(&thd->LOCK_thd_data); - - status = ((thd->wsrep_exec_mode == REPL_RECV) || - (thd->wsrep_exec_mode == TOTAL_ORDER) || - (thd->wsrep_exec_mode == LOCAL_COMMIT)); - if (sync) mysql_mutex_unlock(&thd->LOCK_thd_data); - } - return status; + /* 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"); + } } -extern "C" -my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync) +/* + Start async rollback process + + Asserts thd->LOCK_thd_data ownership + */ +void wsrep_fire_rollbacker(THD *thd) { - bool status = FALSE; - if (thd_ptr) + DBUG_ASSERT(thd->wsrep_trx().state() == wsrep::transaction::s_aborting); + DBUG_PRINT("wsrep",("enqueuing trx abort for %llu", thd->thread_id)); + WSREP_DEBUG("enqueuing trx abort for (%llu)", thd->thread_id); + if (wsrep_rollback_queue->push_back(thd)) { - THD* thd = (THD*)thd_ptr; - if (sync) mysql_mutex_lock(&thd->LOCK_thd_data); - - status = (thd->wsrep_exec_mode == LOCAL_STATE); - if (sync) mysql_mutex_unlock(&thd->LOCK_thd_data); + WSREP_WARN("duplicate thd %llu for rollbacker", + thd->thread_id); } - return status; } + 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"); - + THD *victim_thd= (THD *) victim_thd_ptr; + THD *bf_thd= (THD *) bf_thd_ptr; + mysql_mutex_lock(&victim_thd->LOCK_thd_data); if ( (WSREP(bf_thd) || ( (WSREP_ON || bf_thd->variables.wsrep_OSU_method == WSREP_OSU_RSU) && - bf_thd->wsrep_exec_mode == TOTAL_ORDER) ) && - victim_thd) + wsrep_thd_is_toi(bf_thd)) ) && + victim_thd && + !wsrep_thd_is_aborting(victim_thd)) { - if ((victim_thd->wsrep_conflict_state == MUST_ABORT) || - (victim_thd->wsrep_conflict_state == ABORTED) || - (victim_thd->wsrep_conflict_state == ABORTING)) - { - 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); - ha_abort_transaction(bf_thd, victim_thd, signal); + 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_thd_data); + ha_abort_transaction(bf_thd, victim_thd, signal); + mysql_mutex_lock(&victim_thd->LOCK_thd_data); } else { WSREP_DEBUG("wsrep_abort_thd not effective: %p %p", bf_thd, victim_thd); } - + mysql_mutex_unlock(&victim_thd->LOCK_thd_data); DBUG_RETURN(1); } -extern "C" -int wsrep_thd_in_locking_session(void *thd_ptr) +bool wsrep_bf_abort(const THD* bf_thd, THD* victim_thd) { - if (thd_ptr && ((THD *)thd_ptr)->in_lock_tables) { - return 1; + WSREP_LOG_THD((THD*)bf_thd, "BF aborter before"); + WSREP_LOG_THD(victim_thd, "victim before"); + wsrep::seqno bf_seqno(bf_thd->wsrep_trx().ws_meta().seqno()); + + if (WSREP(victim_thd) && !victim_thd->wsrep_trx().active()) + { + WSREP_DEBUG("wsrep_bf_abort, BF abort for non active transaction"); + wsrep_start_transaction(victim_thd, victim_thd->wsrep_next_trx_id()); } - return 0; -} -bool wsrep_thd_has_explicit_locks(THD *thd) -{ - assert(thd); - return thd->mdl_context.has_explicit_locks(); + bool ret; + if (wsrep_thd_is_toi(bf_thd)) + { + ret= victim_thd->wsrep_cs().total_order_bf_abort(bf_seqno); + } + else + { + ret= victim_thd->wsrep_cs().bf_abort(bf_seqno); + } + if (ret) + { + wsrep_bf_aborts_counter++; + } + return ret; } + diff --git a/sql/wsrep_thd.h b/sql/wsrep_thd.h index 5900668f3fb..3114e02e1b8 100644 --- a/sql/wsrep_thd.h +++ b/sql/wsrep_thd.h @@ -13,42 +13,220 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include <my_config.h> - #ifndef WSREP_THD_H #define WSREP_THD_H -#ifdef WITH_WSREP +#include <my_config.h> +#include "mysql/service_wsrep.h" +#include "wsrep/client_state.hpp" #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(); +bool wsrep_bf_abort(const THD*, THD*); int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, my_bool signal); - -/* - 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_wsrep(void *thd_ptr); +THD* wsrep_start_SR_THD(char *thread_stack); +void wsrep_end_SR_THD(THD* thd); + +/** + 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) +{ + DBUG_ASSERT(error != ER_ERROR_DURING_COMMIT); + 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, + enum wsrep::provider::status 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); + } +} + +static inline void wsrep_override_error(THD* thd, + wsrep::client_error ce, + enum wsrep::provider::status status) +{ + DBUG_ASSERT(ce != wsrep::e_success); + switch (ce) + { + case wsrep::e_error_during_commit: + wsrep_override_error(thd, ER_ERROR_DURING_COMMIT, status); + break; + case wsrep::e_deadlock_error: + wsrep_override_error(thd, ER_LOCK_DEADLOCK); + break; + case wsrep::e_interrupted_error: + wsrep_override_error(thd, ER_QUERY_INTERRUPTED); + break; + case wsrep::e_size_exceeded_error: + wsrep_override_error(thd, ER_ERROR_DURING_COMMIT, status); + break; + case wsrep::e_append_fragment_error: + /* TODO: Figure out better error number */ + wsrep_override_error(thd, ER_ERROR_DURING_COMMIT, status); + break; + case wsrep::e_not_supported_error: + wsrep_override_error(thd, ER_NOT_SUPPORTED_YET); + break; + case wsrep::e_timeout_error: + wsrep_override_error(thd, ER_LOCK_WAIT_TIMEOUT); + break; + default: + wsrep_override_error(thd, ER_UNKNOWN_ERROR); + break; + } +} -enum wsrep_conflict_state wsrep_thd_conflict_state(void *thd_ptr, my_bool sync); -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); +/** + Helper function to log THD wsrep context. -#else /* WITH_WSREP */ + @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 client_mode: %s client_state: %s trx_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_client_mode_str(thd), + wsrep_thd_client_state_str(thd), + wsrep_thd_transaction_state_str(thd), + (long long)thd->wsrep_next_trx_id(), + (long long)thd->wsrep_trx_id(), + (long long)wsrep_thd_trx_seqno(thd), + thd->wsrep_trx().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_thd_is_BF(T, S) (0) -#define wsrep_abort_thd(X,Y,Z) do { } while(0) -#define wsrep_create_appliers(T) do { } while(0) +#define WSREP_LOG_THD(thd_, message_) wsrep_log_thd(thd_, message_, __FUNCTION__) -#endif #endif /* WSREP_THD_H */ diff --git a/sql/wsrep_trans_observer.h b/sql/wsrep_trans_observer.h new file mode 100644 index 00000000000..a3acc9e78fb --- /dev/null +++ b/sql/wsrep_trans_observer.h @@ -0,0 +1,423 @@ +/* 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 "mysql/service_wsrep.h" +#include "wsrep_applier.h" /* wsrep_apply_error */ +#include "wsrep_xid.h" +#include "wsrep_thd.h" + +#include "my_dbug.h" + +class THD; + +/* + Return true if THD has active wsrep transaction. + */ +static inline bool wsrep_is_active(THD* thd) +{ + return (thd->wsrep_cs().state() != wsrep::client_state::s_none && + thd->wsrep_cs().transaction().active()); +} + +/* + Return true if THD is either committing a transaction or statement + is autocommit. + */ +static inline bool wsrep_is_real(THD* thd, bool all) +{ + return (all || thd->transaction.all.ha_list == 0); +} + +/* + Check if a transaction has generated changes. + */ +static inline bool wsrep_has_changes(THD* thd, my_bool all) +{ + return (thd->wsrep_trx().is_empty() == false); +} + +/* + Check if an active transaction has been BF aborted. + */ +static inline bool wsrep_is_bf_aborted(THD* thd) +{ + return (thd->wsrep_trx().active() && thd->wsrep_trx().bf_aborted()); +} + +static inline int wsrep_check_pk(THD* thd) +{ + 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); + wsrep_override_error(thd, ER_LOCK_DEADLOCK); + return 1; + } + } + } + return 0; +} + +static inline bool wsrep_streaming_enabled(THD* thd) +{ + return (thd->wsrep_sr().fragment_size() > 0); +} + + +static inline int wsrep_start_transaction(THD* thd, wsrep_trx_id_t trx_id) +{ + return (thd->wsrep_cs().state() != wsrep::client_state::s_none ? + thd->wsrep_cs().start_transaction(wsrep::transaction_id(trx_id)) : + 0); +} + +/**/ +static inline int wsrep_start_trx_if_not_started(THD* thd) +{ + int ret= 0; + DBUG_ASSERT(thd->wsrep_next_trx_id() != WSREP_UNDEFINED_TRX_ID); + DBUG_ASSERT(thd->wsrep_cs().mode() == Wsrep_client_state::m_local); + if (thd->wsrep_trx().active() == false) + { + ret= wsrep_start_transaction(thd, thd->wsrep_next_trx_id()); + } + return ret; +} + +/* + Called after each row operation. + + Return zero on succes, non-zero on failure. + */ +static inline int wsrep_after_row(THD* thd, bool) +{ + if (thd->wsrep_cs().state() != wsrep::client_state::s_none && + wsrep_thd_is_local(thd)) + { + if (wsrep_check_pk(thd)) + { + return 1; + } + else if (wsrep_streaming_enabled(thd)) + { + return thd->wsrep_cs().after_row(); + } + } + return 0; +} + +/* + Helper method to determine whether commit time hooks + should be run for the transaction. + */ +static inline bool wsrep_run_commit_hook(THD* thd, bool all) +{ + return (wsrep_is_real(thd, all) && wsrep_is_active(thd) && + (wsrep_thd_is_applying(thd) || wsrep_has_changes(thd, all))); +} + +/* + Called before the transaction is prepared. + + Return zero on succes, non-zero on failure. + */ +static inline int wsrep_before_prepare(THD* thd, bool all) +{ + DBUG_ENTER("wsrep_before_prepare"); + WSREP_DEBUG("wsrep_before_prepare: %d", wsrep_is_real(thd, all)); + int ret= 0; + if (wsrep_run_commit_hook(thd, all)) + { + if ((ret= thd->wsrep_cs().before_prepare()) == 0) + { + DBUG_ASSERT(!thd->wsrep_trx().ws_meta().gtid().is_undefined()); + wsrep_xid_init(&thd->wsrep_xid, + thd->wsrep_trx().ws_meta().gtid()); + } + } + DBUG_RETURN(ret); +} + +/* + Called after the transaction has been prepared. + + Return zero on succes, non-zero on failure. + */ +static inline int wsrep_after_prepare(THD* thd, bool all) +{ + DBUG_ENTER("wsrep_after_prepare"); + WSREP_DEBUG("wsrep_after_prepare: %d", wsrep_is_real(thd, all)); + int ret= (wsrep_run_commit_hook(thd, all) ? + thd->wsrep_cs().after_prepare() : 0); + DBUG_ASSERT(ret == 0 || thd->wsrep_cs().current_error() || + thd->wsrep_cs().transaction().state() == wsrep::transaction::s_must_replay); + DBUG_RETURN(ret); +} + + +/* + 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. + */ +static inline int wsrep_before_commit(THD* thd, bool all) +{ + DBUG_ENTER("wsrep_before_commit"); + WSREP_DEBUG("wsrep_before_commit: %d, %lld", + wsrep_is_real(thd, all), + (long long)wsrep_thd_trx_seqno(thd)); + int ret= 0; + if (wsrep_run_commit_hook(thd, all)) + { + if ((ret= thd->wsrep_cs().before_commit()) == 0) + { + DBUG_ASSERT(!thd->wsrep_trx().ws_meta().gtid().is_undefined()); + wsrep_xid_init(&thd->wsrep_xid, + thd->wsrep_trx().ws_meta().gtid()); + } + } + DBUG_RETURN(ret); +} + +/* + 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. + */ +static inline int wsrep_ordered_commit(THD* thd, + bool all, + const wsrep_apply_error&) +{ + DBUG_ENTER("wsrep_ordered_commit"); + WSREP_DEBUG("wsrep_ordered_commit: %d", wsrep_is_real(thd, all)); + DBUG_RETURN(wsrep_run_commit_hook(thd, all) ? + thd->wsrep_cs().ordered_commit() : 0); +} + +/* + Called after the transaction has been committed. + + Return zero on succes, non-zero on failure. + */ +static inline int wsrep_after_commit(THD* thd, bool all) +{ + DBUG_ENTER("wsrep_after_commit"); + WSREP_DEBUG("wsrep_after_commit: %d, %d, %lld, %d", + wsrep_is_real(thd, all), + wsrep_is_active(thd), + (long long)wsrep_thd_trx_seqno(thd), + wsrep_has_changes(thd, all)); + if (wsrep_run_commit_hook(thd, all)) + { + DBUG_RETURN((wsrep_ordered_commit_if_no_binlog(thd, all) || + (thd->wsrep_xid.null(), + thd->wsrep_cs().after_commit()))); + } + DBUG_RETURN(0); +} + +/* + Called before the transaction is rolled back. + + Return zero on succes, non-zero on failure. + */ +static inline int wsrep_before_rollback(THD* thd, bool all) +{ + DBUG_ENTER("wsrep_before_rollback"); + int ret= 0; + if (wsrep_is_active(thd)) + { + if (!all && thd->in_active_multi_stmt_transaction() && + thd->wsrep_trx().is_streaming() && + !wsrep_stmt_rollback_is_safe(thd)) + { + /* Non-safe statement rollback during SR multi statement + transasction. Self abort the transaction, the actual rollback + and error handling will be done in after statement phase. */ + wsrep_thd_self_abort(thd); + ret= 0; + } + else if (wsrep_is_real(thd, all) && + thd->wsrep_trx().state() != wsrep::transaction::s_aborted) + { + /* Real transaction rolling back and wsrep abort not completed + yet */ + /* Reset XID so that it does not trigger writing serialization + history in InnoDB. This needs to be avoided because rollback + may happen out of order and replay may follow. */ + thd->wsrep_xid.null(); + ret= thd->wsrep_cs().before_rollback(); + } + } + DBUG_RETURN(ret); +} + +/* + Called after the transaction has been rolled back. + + Return zero on succes, non-zero on failure. + */ +static inline int wsrep_after_rollback(THD* thd, bool all) +{ + DBUG_ENTER("wsrep_after_rollback"); + DBUG_RETURN((wsrep_is_real(thd, all) && wsrep_is_active(thd) && + thd->wsrep_cs().transaction().state() != + wsrep::transaction::s_aborted) ? + thd->wsrep_cs().after_rollback() : 0); +} + +static inline int wsrep_before_statement(THD* thd) +{ + return (thd->wsrep_cs().state() != wsrep::client_state::s_none ? + thd->wsrep_cs().before_statement() : 0); +} + +static inline +int wsrep_after_statement(THD* thd) +{ + DBUG_ENTER("wsrep_after_statement"); + DBUG_RETURN(thd->wsrep_cs().state() != wsrep::client_state::s_none ? + thd->wsrep_cs().after_statement() : 0); +} + +static inline void wsrep_after_apply(THD* thd) +{ + DBUG_ASSERT(wsrep_thd_is_applying(thd)); + WSREP_DEBUG("wsrep_after_apply %lld", thd->thread_id); + thd->wsrep_cs().after_applying(); +} + +static inline void wsrep_open(THD* thd) +{ + DBUG_ENTER("wsrep_open"); + if (wsrep_on(thd)) + { + thd->wsrep_cs().open(wsrep::client_id(thd->thread_id)); + thd->wsrep_cs().debug_log_level(wsrep_debug); + if (!thd->wsrep_applier && thd->variables.wsrep_trx_fragment_size) + { + thd->wsrep_cs().enable_streaming( + wsrep_fragment_unit(thd->variables.wsrep_trx_fragment_unit), + size_t(thd->variables.wsrep_trx_fragment_size)); + } + } + DBUG_VOID_RETURN; +} + +static inline void wsrep_close(THD* thd) +{ + DBUG_ENTER("wsrep_close"); + if (thd->wsrep_cs().state() != wsrep::client_state::s_none) + { + thd->wsrep_cs().close(); + } + DBUG_VOID_RETURN; +} + +static inline int wsrep_before_command(THD* thd) +{ + return (thd->wsrep_cs().state() != wsrep::client_state::s_none ? + thd->wsrep_cs().before_command() : 0); +} +/* + Called after each command. + + Return zero on success, non-zero on failure. +*/ +static inline void wsrep_after_command_before_result(THD* thd) +{ + if (thd->wsrep_cs().state() != wsrep::client_state::s_none) + { + thd->wsrep_cs().after_command_before_result(); + } +} + +static inline void wsrep_after_command_after_result(THD* thd) +{ + if (thd->wsrep_cs().state() != wsrep::client_state::s_none) + { + thd->wsrep_cs().after_command_after_result(); + } +} + +static inline void wsrep_after_command_ignore_result(THD* thd) +{ + wsrep_after_command_before_result(thd); + DBUG_ASSERT(!thd->wsrep_cs().current_error()); + wsrep_after_command_after_result(thd); +} + +static inline enum wsrep::client_error wsrep_current_error(THD* thd) +{ + return thd->wsrep_cs().current_error(); +} + +static inline enum wsrep::provider::status +wsrep_current_error_status(THD* thd) +{ + return thd->wsrep_cs().current_error_status(); +} + + +/* + Commit an empty transaction. + + If the transaction is real and the wsrep transaction is still active, + the transaction did not generate any rows or keys and is committed + as empty. Here the wsrep transaction is rolled back and after statement + step is performed to leave the wsrep transaction in the state as it + never existed. +*/ +static inline void wsrep_commit_empty(THD* thd, bool all) +{ + DBUG_ENTER("wsrep_commit_empty"); + WSREP_DEBUG("wsrep_commit_empty(%llu)", thd->thread_id); + if (wsrep_is_real(thd, all) && + wsrep_thd_is_local(thd) && + thd->wsrep_trx().active() && + thd->wsrep_trx().state() != wsrep::transaction::s_committed) + { + bool have_error= wsrep_current_error(thd); + int ret= wsrep_before_rollback(thd, all) || + wsrep_after_rollback(thd, all) || + wsrep_after_statement(thd); + DBUG_ASSERT(have_error || !wsrep_current_error(thd)); + if (ret) + { + WSREP_DEBUG("wsrep_commit_empty failed: %d", wsrep_current_error(thd)); + } + } + DBUG_VOID_RETURN; +} + +#endif /* WSREP_TRANS_OBSERVER */ diff --git a/sql/wsrep_types.h b/sql/wsrep_types.h new file mode 100644 index 00000000000..9da00e305a7 --- /dev/null +++ b/sql/wsrep_types.h @@ -0,0 +1,29 @@ +/* Copyright 2018 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +/* + Wsrep typedefs to better conform to coding style. + */ +#ifndef WSREP_TYPES_H +#define WSREP_TYPES_H + +#include "wsrep/seqno.hpp" +#include "wsrep/view.hpp" + +typedef wsrep::id Wsrep_id; +typedef wsrep::seqno Wsrep_seqno; +typedef wsrep::view Wsrep_view; + +#endif /* WSREP_TYPES_H */ diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc index 3c341e222b3..8db0f7be99a 100644 --- a/sql/wsrep_utils.cc +++ b/sql/wsrep_utils.cc @@ -21,6 +21,8 @@ #endif #include "mariadb.h" +#include "my_global.h" +#include "wsrep_api.h" #include "wsrep_utils.h" #include "wsrep_mysqld.h" @@ -47,7 +49,7 @@ static wsp::string wsrep_PATH; void wsrep_prepend_PATH (const char* path) { - int count = 0; + int count= 0; while (environ[count]) { @@ -72,7 +74,7 @@ wsrep_prepend_PATH (const char* path) old_path + strlen("PATH=")); wsrep_PATH.set (new_path); - environ[count] = new_path; + environ[count]= new_path; } else { @@ -93,28 +95,28 @@ namespace wsp bool env::ctor_common(char** e) { - env_ = static_cast<char**>(malloc((len_ + 1) * sizeof(char*))); + env_= static_cast<char**>(malloc((len_ + 1) * sizeof(char*))); if (env_) { for (size_t i(0); i < len_; ++i) { assert(e[i]); // caller should make sure about len_ - env_[i] = strdup(e[i]); + env_[i]= strdup(e[i]); if (!env_[i]) { - errno_ = errno; + errno_= errno; WSREP_ERROR("Failed to allocate env. var: %s", e[i]); return true; } } - env_[len_] = NULL; + env_[len_]= NULL; return false; } else { - errno_ = errno; + errno_= errno; WSREP_ERROR("Failed to allocate env. var vector of length: %zu", len_); return true; } @@ -128,15 +130,15 @@ env::dtor() /* don't need to go beyond the first NULL */ for (size_t i(0); env_[i] != NULL; ++i) { free(env_[i]); } free(env_); - env_ = NULL; + env_= NULL; } - len_ = 0; + len_= 0; } env::env(char** e) : len_(0), env_(NULL), errno_(0) { - if (!e) { e = environ; } + if (!e) { e= environ; } /* count the size of the vector */ while (e[len_]) { ++len_; } @@ -154,21 +156,21 @@ env::~env() { dtor(); } int env::append(const char* val) { - char** tmp = static_cast<char**>(realloc(env_, (len_ + 2)*sizeof(char*))); + char** tmp= static_cast<char**>(realloc(env_, (len_ + 2)*sizeof(char*))); if (tmp) { - env_ = tmp; - env_[len_] = strdup(val); + env_= tmp; + env_[len_]= strdup(val); if (env_[len_]) { ++len_; - env_[len_] = NULL; + env_[len_]= NULL; } - else errno_ = errno; + else errno_= errno; } - else errno_ = errno; + else errno_= errno; return errno_; } @@ -189,7 +191,7 @@ process::process (const char* cmd, const char* type, char** env) if (0 == str_) { WSREP_ERROR ("Can't allocate command line of size: %zu", strlen(cmd)); - err_ = ENOMEM; + err_= ENOMEM; return; } @@ -205,12 +207,12 @@ process::process (const char* cmd, const char* type, char** env) return; } - if (NULL == env) { env = environ; } // default to global environment + if (NULL == env) { env= environ; } // default to global environment - int pipe_fds[2] = { -1, }; + int pipe_fds[2]= { -1, }; if (::pipe(pipe_fds)) { - err_ = errno; + err_= errno; WSREP_ERROR ("pipe() failed: %d (%s)", err_, strerror(err_)); return; } @@ -220,16 +222,16 @@ process::process (const char* cmd, const char* type, char** env) int const child_end (parent_end == PIPE_READ ? PIPE_WRITE : PIPE_READ); int const close_fd (parent_end == PIPE_READ ? STDOUT_FD : STDIN_FD); - char* const pargv[4] = { strdup("sh"), strdup("-c"), strdup(str_), NULL }; + char* const pargv[4]= { strdup("sh"), strdup("-c"), strdup(str_), NULL }; if (!(pargv[0] && pargv[1] && pargv[2])) { - err_ = ENOMEM; + err_= ENOMEM; WSREP_ERROR ("Failed to allocate pargv[] array."); goto cleanup_pipe; } posix_spawnattr_t attr; - err_ = posix_spawnattr_init (&attr); + err_= posix_spawnattr_init (&attr); if (err_) { WSREP_ERROR ("posix_spawnattr_init() failed: %d (%s)", @@ -239,7 +241,7 @@ process::process (const char* cmd, const char* type, char** env) /* make sure that no signlas are masked in child process */ sigset_t sigmask_empty; sigemptyset(&sigmask_empty); - err_ = posix_spawnattr_setsigmask(&attr, &sigmask_empty); + err_= posix_spawnattr_setsigmask(&attr, &sigmask_empty); if (err_) { WSREP_ERROR ("posix_spawnattr_setsigmask() failed: %d (%s)", @@ -255,7 +257,7 @@ process::process (const char* cmd, const char* type, char** env) sigaddset(&default_signals, SIGPIPE); sigaddset(&default_signals, SIGTERM); sigaddset(&default_signals, SIGCHLD); - err_ = posix_spawnattr_setsigdefault(&attr, &default_signals); + err_= posix_spawnattr_setsigdefault(&attr, &default_signals); if (err_) { WSREP_ERROR ("posix_spawnattr_setsigdefault() failed: %d (%s)", @@ -263,7 +265,7 @@ process::process (const char* cmd, const char* type, char** env) goto cleanup_attr; } - err_ = posix_spawnattr_setflags (&attr, POSIX_SPAWN_SETSIGDEF | + err_= posix_spawnattr_setflags (&attr, POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_USEVFORK); if (err_) @@ -274,7 +276,7 @@ process::process (const char* cmd, const char* type, char** env) } posix_spawn_file_actions_t fact; - err_ = posix_spawn_file_actions_init (&fact); + err_= posix_spawn_file_actions_init (&fact); if (err_) { WSREP_ERROR ("posix_spawn_file_actions_init() failed: %d (%s)", @@ -283,7 +285,7 @@ process::process (const char* cmd, const char* type, char** env) } // close child's stdout|stdin depending on what we returning - err_ = posix_spawn_file_actions_addclose (&fact, close_fd); + err_= posix_spawn_file_actions_addclose (&fact, close_fd); if (err_) { WSREP_ERROR ("posix_spawn_file_actions_addclose() failed: %d (%s)", @@ -292,7 +294,7 @@ process::process (const char* cmd, const char* type, char** env) } // substitute our pipe descriptor in place of the closed one - err_ = posix_spawn_file_actions_adddup2 (&fact, + err_= posix_spawn_file_actions_adddup2 (&fact, pipe_fds[child_end], close_fd); if (err_) { @@ -301,30 +303,30 @@ process::process (const char* cmd, const char* type, char** env) goto cleanup_fact; } - err_ = posix_spawnp (&pid_, pargv[0], &fact, &attr, pargv, env); + err_= posix_spawnp (&pid_, pargv[0], &fact, &attr, pargv, env); if (err_) { WSREP_ERROR ("posix_spawnp(%s) failed: %d (%s)", pargv[2], err_, strerror(err_)); - pid_ = 0; // just to make sure it was not messed up in the call + pid_= 0; // just to make sure it was not messed up in the call goto cleanup_fact; } - io_ = fdopen (pipe_fds[parent_end], type); + io_= fdopen (pipe_fds[parent_end], type); if (io_) { - pipe_fds[parent_end] = -1; // skip close on cleanup + pipe_fds[parent_end]= -1; // skip close on cleanup } else { - err_ = errno; + err_= errno; WSREP_ERROR ("fdopen() failed: %d (%s)", err_, strerror(err_)); } cleanup_fact: int err; // to preserve err_ code - err = posix_spawn_file_actions_destroy (&fact); + err= posix_spawn_file_actions_destroy (&fact); if (err) { WSREP_ERROR ("posix_spawn_file_actions_destroy() failed: %d (%s)\n", @@ -332,7 +334,7 @@ cleanup_fact: } cleanup_attr: - err = posix_spawnattr_destroy (&attr); + err= posix_spawnattr_destroy (&attr); if (err) { WSREP_ERROR ("posix_spawnattr_destroy() failed: %d (%s)", @@ -360,7 +362,7 @@ process::~process () if (fclose (io_) == -1) { - err_ = errno; + err_= errno; WSREP_ERROR("fclose() failed: %d (%s)", err_, strerror(err_)); } } @@ -376,34 +378,34 @@ process::wait () int status; if (-1 == waitpid(pid_, &status, 0)) { - err_ = errno; assert (err_); + err_= errno; assert (err_); WSREP_ERROR("Waiting for process failed: %s, PID(%ld): %d (%s)", str_, (long)pid_, err_, strerror (err_)); } else { // command completed, check exit status if (WIFEXITED (status)) { - err_ = WEXITSTATUS (status); + err_= WEXITSTATUS (status); } else { // command didn't complete with exit() WSREP_ERROR("Process was aborted."); - err_ = errno ? errno : ECHILD; + err_= errno ? errno : ECHILD; } if (err_) { switch (err_) /* Translate error codes to more meaningful */ { - case 126: err_ = EACCES; break; /* Permission denied */ - case 127: err_ = ENOENT; break; /* No such file or directory */ - case 143: err_ = EINTR; break; /* Subprocess killed */ + case 126: err_= EACCES; break; /* Permission denied */ + case 127: err_= ENOENT; break; /* No such file or directory */ + case 143: err_= EINTR; break; /* Subprocess killed */ } WSREP_ERROR("Process completed with error: %s: %d (%s)", str_, err_, strerror(err_)); } - pid_ = 0; + pid_= 0; if (io_) fclose (io_); - io_ = NULL; + io_= NULL; } } else { @@ -421,7 +423,7 @@ thd::thd (my_bool won) : init(), ptr(new THD(0)) ptr->thread_stack= (char*) &ptr; ptr->store_globals(); ptr->variables.option_bits&= ~OPTION_BIN_LOG; // disable binlog - ptr->variables.wsrep_on = won; + ptr->variables.wsrep_on= won; ptr->security_ctx->master_access= ~(ulong)0; lex_start(ptr); } @@ -441,7 +443,7 @@ thd::~thd () /* Returns INADDR_NONE, INADDR_ANY, INADDR_LOOPBACK or something else */ unsigned int wsrep_check_ip (const char* const addr, bool *is_ipv6) { - unsigned int ret = INADDR_NONE; + unsigned int ret= INADDR_NONE; struct addrinfo *res, hints; memset (&hints, 0, sizeof(hints)); @@ -451,7 +453,7 @@ unsigned int wsrep_check_ip (const char* const addr, bool *is_ipv6) *is_ipv6= false; - int gai_ret = getaddrinfo(addr, NULL, &hints, &res); + int gai_ret= getaddrinfo(addr, NULL, &hints, &res); if (0 == gai_ret) { if (AF_INET == res->ai_family) /* IPv4 */ @@ -488,7 +490,9 @@ size_t wsrep_guess_ip (char* buf, size_t buf_len) size_t ret= 0; // Attempt 1: Try to get the IP from bind-address. - if (my_bind_addr_str && my_bind_addr_str[0] != '\0') + // Skip if empty or bind-address=* + if (my_bind_addr_str && my_bind_addr_str[0] != '\0' && + strcmp(my_bind_addr_str, "*") != 0) { bool unused; unsigned int const ip_type= wsrep_check_ip(my_bind_addr_str, &unused); @@ -539,7 +543,7 @@ size_t wsrep_guess_ip (char* buf, size_t buf_len) if (getifaddrs(&ifaddr) == 0) { - for (ifa= ifaddr; ifa != NULL; ifa = ifa->ifa_next) + for (ifa= ifaddr; ifa != NULL; ifa= ifa->ifa_next) { if (!ifa->ifa_addr) continue; diff --git a/sql/wsrep_utils.h b/sql/wsrep_utils.h index 277cea9dc31..147da8e7c52 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::server_state::s_disconnected) {} + void set(enum wsrep::server_state::state new_status, + const wsrep::view* view= 0) + { + if (status != new_status || 0 != view) + { + wsrep_notify_status(new_status, view); + status= new_status; + } + } + enum wsrep::server_state::state get() const { return status; } +private: + enum wsrep::server_state::state 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); @@ -173,52 +194,37 @@ private: class Config_state { public: - Config_state() : view_(), status_(WSREP_MEMBER_UNDEFINED) + Config_state() : view_(), status_(wsrep::server_state::s_disconnected) {} - void set(wsrep_member_status_t status, const wsrep_view_info_t* view) + void set(const wsrep::view& view) { - wsrep_notify_status(status, view); + wsrep_notify_status(status_, &view); lock(); - - status_= status; - view_= *view; - member_info_.clear(); - - wsrep_member_info_t memb; - for(int i= 0; i < view->memb_num; i ++) - { - memb= view->members[i]; - member_info_.append_val(memb); - } - + view_= view; unlock(); } - void set(wsrep_member_status_t status) + void set(enum wsrep::server_state::state status) { - wsrep_notify_status(status, 0); + wsrep_notify_status(status); + lock(); status_= status; unlock(); } - wsrep_view_info_t get_view_info() const + const wsrep::view& get_view_info() const { return view_; } - wsrep_member_status_t get_status() const + enum wsrep::server_state::state get_status() const { return status_; } - Dynamic_array<wsrep_member_info_t> * get_member_info() - { - return &member_info_; - } - int lock() { return mysql_mutex_lock(&LOCK_wsrep_config_state); @@ -230,9 +236,8 @@ public: } private: - wsrep_view_info_t view_; - wsrep_member_status_t status_; - Dynamic_array<wsrep_member_info_t> member_info_; + wsrep::view view_; + enum wsrep::server_state::state status_; }; } /* namespace wsp */ @@ -308,12 +313,23 @@ public: string() : string_(0) {} explicit string(size_t s) : string_(static_cast<char*>(malloc(s))) {} char* operator()() { return string_; } - void set(char* str) { if (string_) free (string_); string_ = str; } + void set(char* str) { if (string_) free (string_); string_= str; } ~string() { set (0); } 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 { @@ -323,7 +339,7 @@ public: lock (pthread_mutex_t* mtx) : mtx_(mtx) { - int err = pthread_mutex_lock (mtx_); + int err= pthread_mutex_lock (mtx_); if (err) { @@ -334,7 +350,7 @@ public: virtual ~lock () { - int err = pthread_mutex_unlock (mtx_); + int err= pthread_mutex_unlock (mtx_); if (err) { diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 1471ad91a96..8a0968639c2 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)); @@ -53,7 +51,7 @@ bool wsrep_on_update (sys_var *self, THD* thd, enum_var_type var_type) { if (var_type == OPT_GLOBAL) { // FIXME: this variable probably should be changed only per session - thd->variables.wsrep_on = global_system_variables.wsrep_on; + thd->variables.wsrep_on= global_system_variables.wsrep_on; } return false; @@ -68,8 +66,8 @@ bool wsrep_on_check(sys_var *self, THD* thd, set_var* var) if (new_wsrep_on && innodb_hton_ptr && innodb_lock_schedule_algorithm != 0) { my_message(ER_WRONG_ARGUMENTS, " WSREP (galera) can't be enabled " - "if innodb_lock_schedule_algorithm=VATS. Please configure" - " innodb_lock_schedule_algorithm=FCFS and restart.", MYF(0)); + "if innodb_lock_schedule_algorithm=VATS. Please configure" + " innodb_lock_schedule_algorithm=FCFS and restart.", MYF(0)); return true; } return false; @@ -77,10 +75,6 @@ bool wsrep_on_check(sys_var *self, THD* thd, set_var* var) bool wsrep_causal_reads_update (sys_var *self, THD* thd, enum_var_type var_type) { - // global setting should not affect session setting. - // if (var_type == OPT_GLOBAL) { - // thd->variables.wsrep_causal_reads = global_system_variables.wsrep_causal_reads; - // } if (thd->variables.wsrep_causal_reads) { thd->variables.wsrep_sync_wait |= WSREP_SYNC_WAIT_BEFORE_READ; } else { @@ -99,15 +93,11 @@ bool wsrep_causal_reads_update (sys_var *self, THD* thd, enum_var_type var_type) bool wsrep_sync_wait_update (sys_var* self, THD* thd, enum_var_type var_type) { - // global setting should not affect session setting. - // if (var_type == OPT_GLOBAL) { - // thd->variables.wsrep_sync_wait = global_system_variables.wsrep_sync_wait; - // } - thd->variables.wsrep_causal_reads = thd->variables.wsrep_sync_wait & + thd->variables.wsrep_causal_reads= thd->variables.wsrep_sync_wait & WSREP_SYNC_WAIT_BEFORE_READ; // update global settings too - global_system_variables.wsrep_causal_reads = global_system_variables.wsrep_sync_wait & + global_system_variables.wsrep_causal_reads= global_system_variables.wsrep_sync_wait & WSREP_SYNC_WAIT_BEFORE_READ; return false; @@ -129,7 +119,7 @@ bool wsrep_start_position_verify (const char* start_str) ssize_t uuid_len; // Check whether it has minimum acceptable length. - start_len = strlen (start_str); + start_len= strlen (start_str); if (start_len < 34) return true; @@ -137,7 +127,7 @@ bool wsrep_start_position_verify (const char* start_str) Parse the input to check whether UUID length is acceptable and seqno has been provided. */ - uuid_len = wsrep_uuid_scan (start_str, start_len, &uuid); + uuid_len= wsrep_uuid_scan (start_str, start_len, &uuid); if (uuid_len < 0 || (start_len - uuid_len) < 2) return true; @@ -157,19 +147,18 @@ 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); + 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, uuid, seqno, NULL, 0); } else { - // initialization - local_uuid = uuid; - local_seqno = seqno; + local_uuid= uuid; + local_seqno= seqno; } return false; } @@ -194,7 +183,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 +215,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; @@ -263,25 +252,23 @@ end: static bool refresh_provider_options() { - DBUG_ASSERT(wsrep); - WSREP_DEBUG("refresh_provider_options: %s", (wsrep_provider_options) ? wsrep_provider_options : "null"); - char* opts= wsrep->options_get(wsrep); - if (opts) + + try { - wsrep_provider_options_init(opts); + std::string opts= Wsrep_server_state::instance().provider().options(); + wsrep_provider_options_init(opts.c_str()); get_provider_option_value(wsrep_provider_options, (char*)"repl.max_ws_size", &wsrep_max_ws_size); - free(opts); + return false; } - else + catch (...) { WSREP_ERROR("Failed to get provider options"); return true; } - return false; } static int wsrep_provider_verify (const char* provider_str) @@ -332,8 +319,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); @@ -346,7 +331,12 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type) */ 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); @@ -357,17 +347,17 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type) if (wsrep_init()) { my_error(ER_CANT_OPEN_LIBRARY, MYF(0), tmp, my_error, "wsrep_init failed"); - rcode = true; + rcode= true; } free(tmp); // 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; } @@ -385,12 +375,12 @@ void wsrep_provider_init (const char* value) } if (wsrep_provider) my_free((void *)wsrep_provider); - wsrep_provider = my_strdup(value, MYF(0)); + wsrep_provider= my_strdup(value, MYF(0)); } bool wsrep_provider_options_check(sys_var *self, THD* thd, set_var* var) { - if (wsrep == NULL) + if (!WSREP_ON) { my_message(ER_WRONG_ARGUMENTS, "WSREP (galera) not started", MYF(0)); return true; @@ -400,9 +390,9 @@ bool wsrep_provider_options_check(sys_var *self, THD* thd, set_var* var) bool wsrep_provider_options_update(sys_var *self, THD* thd, enum_var_type type) { - DBUG_ASSERT(wsrep); - wsrep_status_t ret= wsrep->options_set(wsrep, wsrep_provider_options); - if (ret != WSREP_OK) + enum wsrep::provider::status ret= + Wsrep_server_state::instance().provider().options(wsrep_provider_options); + if (ret) { WSREP_ERROR("Set options returned %d", ret); refresh_provider_options(); @@ -415,7 +405,7 @@ void wsrep_provider_options_init(const char* value) { if (wsrep_provider_options && wsrep_provider_options != value) my_free((void *)wsrep_provider_options); - wsrep_provider_options = (value) ? my_strdup(value, MYF(0)) : NULL; + wsrep_provider_options= (value) ? my_strdup(value, MYF(0)) : NULL; } bool wsrep_reject_queries_update(sys_var *self, THD* thd, enum_var_type type) @@ -469,18 +459,12 @@ 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) + if (!Wsrep_server_state::instance().is_provider_loaded()) { - WSREP_INFO("wsrep provider is not loaded, can't re(start) replication."); + WSREP_INFO("WSREP (galera) provider is not loaded, can't re(start) replication."); 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. @@ -491,13 +475,6 @@ bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type) 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()) { @@ -505,7 +482,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; } @@ -590,15 +573,14 @@ void wsrep_node_address_init (const char* value) if (wsrep_node_address && strcmp(wsrep_node_address, value)) my_free ((void*)wsrep_node_address); - wsrep_node_address = (value) ? my_strdup(value, MYF(0)) : NULL; + wsrep_node_address= (value) ? my_strdup(value, MYF(0)) : NULL; } static void wsrep_slave_count_change_update () { - wsrep_slave_count_change = (wsrep_slave_threads - wsrep_prev_slave_threads); + wsrep_slave_count_change= (wsrep_slave_threads - wsrep_running_threads + 2); WSREP_DEBUG("Change on slave threads: New %lu old %lu difference %d", - wsrep_slave_threads, wsrep_prev_slave_threads, wsrep_slave_count_change); - wsrep_prev_slave_threads = wsrep_slave_threads; + wsrep_slave_threads, wsrep_running_threads, wsrep_slave_count_change); } bool wsrep_slave_threads_update (sys_var *self, THD* thd, enum_var_type type) @@ -607,14 +589,14 @@ bool wsrep_slave_threads_update (sys_var *self, THD* thd, enum_var_type type) if (wsrep_slave_count_change > 0) { wsrep_create_appliers(wsrep_slave_count_change); - wsrep_slave_count_change = 0; + wsrep_slave_count_change= 0; } return false; } bool wsrep_desync_check (sys_var *self, THD* thd, set_var* var) { - if (wsrep == NULL) + if (!WSREP_ON) { my_message(ER_WRONG_ARGUMENTS, "WSREP (galera) not started", MYF(0)); return true; @@ -639,17 +621,17 @@ bool wsrep_desync_check (sys_var *self, THD* thd, set_var* var) } return false; } - wsrep_status_t ret(WSREP_WARNING); + int ret= 1; if (new_wsrep_desync) { - ret = wsrep->desync (wsrep); - if (ret != WSREP_OK) { - WSREP_WARN ("SET desync failed %d for schema: %s, query: %s", - ret, thd->get_db(), thd->query()); + ret= Wsrep_server_state::instance().provider().desync(); + if (ret) { + WSREP_WARN ("SET desync failed %d for schema: %s, query: %s", ret, + thd->db.str, WSREP_QUERY(thd)); my_error (ER_CANNOT_USER, MYF(0), "'desync'", thd->query()); return true; } } else { - ret = wsrep->resync (wsrep); + ret= Wsrep_server_state::instance().provider().resync(); if (ret != WSREP_OK) { WSREP_WARN ("SET resync failed %d for schema: %s, query: %s", ret, thd->get_db(), thd->query()); @@ -662,13 +644,70 @@ bool wsrep_desync_check (sys_var *self, THD* thd, set_var* var) bool wsrep_desync_update (sys_var *self, THD* thd, enum_var_type type) { - DBUG_ASSERT(wsrep); + 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_trx_fragment_size_update(sys_var* self, THD *thd, enum_var_type) +{ + WSREP_DEBUG("wsrep_trx_fragment_size_update: %llu", + thd->variables.wsrep_trx_fragment_size); + if (thd->variables.wsrep_trx_fragment_size) + { + return thd->wsrep_cs().enable_streaming( + wsrep_fragment_unit(thd->variables.wsrep_trx_fragment_unit), + size_t(thd->variables.wsrep_trx_fragment_size)); + } + else + { + thd->wsrep_cs().disable_streaming(); + return false; + } +} + +bool wsrep_trx_fragment_unit_update(sys_var* self, THD *thd, enum_var_type) +{ + WSREP_DEBUG("wsrep_trx_fragment_unit_update: %lu", + thd->variables.wsrep_trx_fragment_unit); + if (thd->variables.wsrep_trx_fragment_size) + { + return thd->wsrep_cs().enable_streaming( + wsrep_fragment_unit(thd->variables.wsrep_trx_fragment_unit), + size_t(thd->variables.wsrep_trx_fragment_size)); + } return false; } bool wsrep_max_ws_size_check(sys_var *self, THD* thd, set_var* var) { - if (wsrep == NULL) + if (!WSREP_ON) { my_message(ER_WRONG_ARGUMENTS, "WSREP (galera) not started", MYF(0)); return true; @@ -676,36 +715,35 @@ bool wsrep_max_ws_size_check(sys_var *self, THD* thd, set_var* var) return false; } -bool wsrep_max_ws_size_update (sys_var *self, THD *thd, enum_var_type) +bool wsrep_max_ws_size_update(sys_var *self, THD *thd, enum_var_type) { - DBUG_ASSERT(wsrep); - char max_ws_size_opt[128]; my_snprintf(max_ws_size_opt, sizeof(max_ws_size_opt), - "repl.max_ws_size=%lu", wsrep_max_ws_size); - wsrep_status_t ret= wsrep->options_set(wsrep, max_ws_size_opt); - if (ret != WSREP_OK) + "repl.max_ws_size=%d", wsrep_max_ws_size); + enum wsrep::provider::status ret= Wsrep_server_state::instance().provider().options(max_ws_size_opt); + if (ret) { WSREP_ERROR("Set options returned %d", ret); - refresh_provider_options(); return true; } return refresh_provider_options(); } +#if UNUSED /* eaec266eb16c (Sergei Golubchik 2014-09-28) */ 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} }; @@ -713,49 +751,90 @@ static int show_var_cmp(const void *var1, const void *var2) { return strcasecmp(((SHOW_VAR*)var1)->name, ((SHOW_VAR*)var2)->name); } +#endif /* UNUSED */ +/* + * Status variables stuff below + */ +static inline void +wsrep_assign_to_mysql (SHOW_VAR* mysql, wsrep_stats_var* wsrep_var) +{ + mysql->name= wsrep_var->name; + switch (wsrep_var->type) { + case WSREP_VAR_INT64: + mysql->value= (char*) &wsrep_var->value._int64; + mysql->type= SHOW_LONGLONG; + break; + case WSREP_VAR_STRING: + mysql->value= (char*) &wsrep_var->value._string; + mysql->type= SHOW_CHAR_PTR; + break; + case WSREP_VAR_DOUBLE: + mysql->value= (char*) &wsrep_var->value._double; + mysql->type= SHOW_DOUBLE; + break; + } +} -int wsrep_show_status (THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +#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) { - uint i, maxi= SHOW_VAR_FUNC_BUFF_SIZE / sizeof(*var) - 1; - SHOW_VAR *v= (SHOW_VAR *)buff; + int wsrep_status_len, i; - var->type= SHOW_ARRAY; - var->value= buff; + thd->wsrep_status_vars= Wsrep_server_state::instance().status(); - for (i=0; i < array_elements(wsrep_status_vars); i++) - *v++= wsrep_status_vars[i]; + wsrep_status_len= thd->wsrep_status_vars.size(); - DBUG_ASSERT(i < maxi); +#if DYNAMIC + if (wsrep_status_len != mysql_status_len) { + void* tmp= realloc (mysql_status_vars, + (wsrep_status_len + 1) * sizeof(SHOW_VAR)); + if (!tmp) { - if (wsrep != NULL) - { - wsrep_stats_var* stats= wsrep->stats_get(wsrep); - for (wsrep_stats_var *sv= stats; - i < maxi && sv && sv->name; i++, - sv++, v++) - { - v->name = thd->strdup(sv->name); - switch (sv->type) { - case WSREP_VAR_INT64: - v->value = (char*)thd->memdup(&sv->value._integer64, sizeof(longlong)); - v->type = SHOW_LONGLONG; - break; - case WSREP_VAR_STRING: - v->value = thd->strdup(sv->value._string); - v->type = SHOW_CHAR; - break; - case WSREP_VAR_DOUBLE: - v->value = (char*)thd->memdup(&sv->value._double, sizeof(double)); - v->type = SHOW_DOUBLE; - break; - } + sql_print_error ("Out of memory for wsrep status variables." + "Number of variables: %d", wsrep_status_len); + return; } - wsrep->stats_free(wsrep, stats); + + 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++) + { + mysql_status_vars[i].name= (char*)thd->wsrep_status_vars[i].name().c_str(); + mysql_status_vars[i].value= (char*)thd->wsrep_status_vars[i].value().c_str(); + mysql_status_vars[i].type= SHOW_CHAR; } - my_qsort(buff, i, sizeof(*v), show_var_cmp); + 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; +} - v->name= 0; // terminator +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) +{ + thd->wsrep_status_vars.clear(); +} diff --git a/sql/wsrep_var.h b/sql/wsrep_var.h index 7d3ff50f1d2..b732fb48b38 100644 --- a/sql/wsrep_var.h +++ b/sql/wsrep_var.h @@ -13,11 +13,11 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include <my_config.h> - #ifndef WSREP_VAR_H #define WSREP_VAR_H +#include <my_config.h> + #ifdef WITH_WSREP #define WSREP_CLUSTER_NAME "my_wsrep_cluster" @@ -90,13 +90,18 @@ 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_trx_fragment_size_check CHECK_ARGS; +extern bool wsrep_trx_fragment_size_update UPDATE_ARGS; + +extern bool wsrep_trx_fragment_unit_update UPDATE_ARGS; + extern bool wsrep_max_ws_size_check CHECK_ARGS; extern bool wsrep_max_ws_size_update UPDATE_ARGS; + extern bool wsrep_reject_queries_update UPDATE_ARGS; #else /* WITH_WSREP */ -#define WSREP_NONE #define wsrep_provider_init(X) #define wsrep_init_vars() (0) #define wsrep_start_position_init(X) diff --git a/sql/wsrep_xid.cc b/sql/wsrep_xid.cc index 2834100568a..a1c454d9d65 100644 --- a/sql/wsrep_xid.cc +++ b/sql/wsrep_xid.cc @@ -21,6 +21,9 @@ #include "sql_class.h" #include "wsrep_mysqld.h" // for logging macros +#include <mysql/service_wsrep.h> + +#include <algorithm> /* std::sort() */ /* * WSREPXid */ @@ -34,20 +37,22 @@ #define WSREP_XID_SEQNO_OFFSET (WSREP_XID_UUID_OFFSET + sizeof(wsrep_uuid_t)) #define WSREP_XID_GTRID_LEN (WSREP_XID_SEQNO_OFFSET + sizeof(wsrep_seqno_t)) -void wsrep_xid_init(XID* xid, const wsrep_uuid_t& uuid, wsrep_seqno_t seqno) +void wsrep_xid_init(XID* xid, const wsrep::gtid& wsgtid) { xid->formatID= 1; xid->gtrid_length= WSREP_XID_GTRID_LEN; xid->bqual_length= 0; memset(xid->data, 0, sizeof(xid->data)); memcpy(xid->data, WSREP_XID_PREFIX, WSREP_XID_PREFIX_LEN); - xid->data[WSREP_XID_VERSION_OFFSET] = WSREP_XID_VERSION_2; - memcpy(xid->data + WSREP_XID_UUID_OFFSET, &uuid, sizeof(wsrep_uuid_t)); - int8store(xid->data + WSREP_XID_SEQNO_OFFSET,seqno); + xid->data[WSREP_XID_VERSION_OFFSET]= WSREP_XID_VERSION_2; + memcpy(xid->data + WSREP_XID_UUID_OFFSET, wsgtid.id().data(),sizeof(wsrep::id)); + int8store(xid->data + WSREP_XID_SEQNO_OFFSET, wsgtid.seqno().get()); } -int wsrep_is_wsrep_xid(const XID* xid) +extern "C" +int wsrep_is_wsrep_xid(const void* xid_ptr) { + const XID* xid= static_cast<const XID*>(xid_ptr); return (xid->formatID == 1 && xid->gtrid_length == WSREP_XID_GTRID_LEN && xid->bqual_length == 0 && @@ -56,33 +61,36 @@ int wsrep_is_wsrep_xid(const XID* xid) xid->data[WSREP_XID_VERSION_OFFSET] == WSREP_XID_VERSION_2)); } -const wsrep_uuid_t* wsrep_xid_uuid(const XID& xid) +const unsigned char* wsrep_xid_uuid(const xid_t* xid) { - if (wsrep_is_wsrep_xid(&xid)) - return reinterpret_cast<const wsrep_uuid_t*>(xid.data - + WSREP_XID_UUID_OFFSET); + DBUG_ASSERT(xid); + static wsrep::id const undefined; + if (wsrep_is_wsrep_xid(xid)) + return reinterpret_cast<const unsigned char*> + (xid->data + WSREP_XID_UUID_OFFSET); else - return &WSREP_UUID_UNDEFINED; + return static_cast<const unsigned char*>(wsrep::id::undefined().data()); } -const unsigned char* wsrep_xid_uuid(const xid_t* xid) +const wsrep::id& wsrep_xid_uuid(const XID& xid) { - DBUG_ASSERT(xid); - return wsrep_xid_uuid(*xid)->data; + compile_time_assert(sizeof(wsrep::id) == sizeof(wsrep_uuid_t)); + return *reinterpret_cast<const wsrep::id*>(wsrep_xid_uuid(&xid)); } -wsrep_seqno_t wsrep_xid_seqno(const XID& xid) +long long wsrep_xid_seqno(const xid_t* xid) { - wsrep_seqno_t ret= WSREP_SEQNO_UNDEFINED; - if (wsrep_is_wsrep_xid(&xid)) + DBUG_ASSERT(xid); + long long ret= wsrep::seqno::undefined().get(); + if (wsrep_is_wsrep_xid(xid)) { - switch (xid.data[WSREP_XID_VERSION_OFFSET]) + switch (xid->data[WSREP_XID_VERSION_OFFSET]) { case WSREP_XID_VERSION_1: - memcpy(&ret, xid.data + WSREP_XID_SEQNO_OFFSET, sizeof ret); + memcpy(&ret, xid->data + WSREP_XID_SEQNO_OFFSET, sizeof ret); break; case WSREP_XID_VERSION_2: - ret= sint8korr(xid.data + WSREP_XID_SEQNO_OFFSET); + ret= sint8korr(xid->data + WSREP_XID_SEQNO_OFFSET); break; default: break; @@ -91,10 +99,9 @@ wsrep_seqno_t wsrep_xid_seqno(const XID& xid) return ret; } -long long wsrep_xid_seqno(const xid_t* xid) +wsrep::seqno wsrep_xid_seqno(const XID& xid) { - DBUG_ASSERT(xid); - return wsrep_xid_seqno(*xid); + return wsrep::seqno(wsrep_xid_seqno(&xid)); } static my_bool set_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) @@ -104,11 +111,11 @@ static my_bool set_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) if (hton->set_checkpoint) { - const wsrep_uuid_t* uuid(wsrep_xid_uuid(*xid)); - char uuid_str[40] = {0, }; - wsrep_uuid_print(uuid, uuid_str, sizeof(uuid_str)); + const unsigned char* uuid= wsrep_xid_uuid(xid); + char uuid_str[40]= {0, }; + wsrep_uuid_print((const wsrep_uuid_t*)uuid, uuid_str, sizeof(uuid_str)); WSREP_DEBUG("Set WSREPXid for InnoDB: %s:%lld", - uuid_str, (long long)wsrep_xid_seqno(*xid)); + uuid_str, (long long)wsrep_xid_seqno(xid)); hton->set_checkpoint(hton, xid); } return FALSE; @@ -120,10 +127,10 @@ bool wsrep_set_SE_checkpoint(XID& xid) &xid); } -bool wsrep_set_SE_checkpoint(const wsrep_uuid_t& uuid, wsrep_seqno_t seqno) +bool wsrep_set_SE_checkpoint(const wsrep::gtid& wsgtid) { XID xid; - wsrep_xid_init(&xid, uuid, seqno); + wsrep_xid_init(&xid, wsgtid); return wsrep_set_SE_checkpoint(xid); } @@ -135,11 +142,12 @@ static my_bool get_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) if (hton->get_checkpoint) { hton->get_checkpoint(hton, xid); - const wsrep_uuid_t* uuid(wsrep_xid_uuid(*xid)); - char uuid_str[40] = {0, }; - wsrep_uuid_print(uuid, uuid_str, sizeof(uuid_str)); + wsrep_uuid_t uuid; + memcpy(&uuid, wsrep_xid_uuid(xid), sizeof(uuid)); + char uuid_str[40]= {0, }; + wsrep_uuid_print(&uuid, uuid_str, sizeof(uuid_str)); WSREP_DEBUG("Read WSREPXid from InnoDB: %s:%lld", - uuid_str, (long long)wsrep_xid_seqno(*xid)); + uuid_str, (long long)wsrep_xid_seqno(xid)); } return FALSE; } @@ -150,32 +158,58 @@ bool wsrep_get_SE_checkpoint(XID& xid) &xid); } -bool wsrep_get_SE_checkpoint(wsrep_uuid_t& uuid, wsrep_seqno_t& seqno) +wsrep::gtid wsrep_get_SE_checkpoint() { - uuid= WSREP_UUID_UNDEFINED; - seqno= WSREP_SEQNO_UNDEFINED; - XID xid; xid.null(); if (wsrep_get_SE_checkpoint(xid)) { - return true; + return wsrep::gtid(); } if (xid.is_null()) { - return false; + return wsrep::gtid(); } if (!wsrep_is_wsrep_xid(&xid)) { WSREP_WARN("Read non-wsrep XID from storage engines."); - return false; + return wsrep::gtid(); } - uuid= *wsrep_xid_uuid(xid); - seqno= wsrep_xid_seqno(xid); + return wsrep::gtid(wsrep_xid_uuid(xid),wsrep_xid_seqno(xid)); +} + +/* + Sort order for XIDs. Wsrep XIDs are sorted according to + seqno in ascending order. Non-wsrep XIDs are considered + equal among themselves and greater than with respect + to wsrep XIDs. + */ +struct Wsrep_xid_cmp +{ + bool operator()(const XID& left, const XID& right) const + { + const bool left_is_wsrep= wsrep_is_wsrep_xid(&left); + const bool right_is_wsrep= wsrep_is_wsrep_xid(&right); + if (left_is_wsrep && right_is_wsrep) + { + return (wsrep_xid_seqno(&left) < wsrep_xid_seqno(&right)); + } + else if (left_is_wsrep) + { + return true; + } + else + { + return false; + } + } +}; - return false; +void wsrep_sort_xid_array(XID *array, int len) +{ + std::sort(array, array + len, Wsrep_xid_cmp()); } diff --git a/sql/wsrep_xid.h b/sql/wsrep_xid.h index 5b33a904de1..e41f6fba420 100644 --- a/sql/wsrep_xid.h +++ b/sql/wsrep_xid.h @@ -20,17 +20,19 @@ #ifdef WITH_WSREP -#include "../wsrep/wsrep_api.h" +#include "wsrep/gtid.hpp" #include "handler.h" // XID typedef -void wsrep_xid_init(xid_t*, const wsrep_uuid_t&, wsrep_seqno_t); -const wsrep_uuid_t* wsrep_xid_uuid(const XID&); -wsrep_seqno_t wsrep_xid_seqno(const XID&); +void wsrep_xid_init(xid_t*, const wsrep::gtid&); +const wsrep::id& wsrep_xid_uuid(const XID&); +wsrep::seqno wsrep_xid_seqno(const XID&); +wsrep::gtid wsrep_get_SE_checkpoint(); +bool wsrep_set_SE_checkpoint(const wsrep::gtid& gtid); //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_sort_xid_array(XID *array, int len); #endif /* WITH_WSREP */ #endif /* WSREP_UTILS_H */ diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index c8e7236dc93..2747a6fa338 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -822,7 +822,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 @@ -856,7 +856,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 2690ff9f736..186c3ee3154 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -131,6 +131,9 @@ void close_thread_tables(THD* thd); #define tdc_size 400 #endif +#include <mysql/plugin.h> +#include <mysql/service_wsrep.h> + #include "ha_innodb.h" #include "i_s.h" #include "sync0sync.h" @@ -138,9 +141,6 @@ void close_thread_tables(THD* thd); #include <string> #include <sstream> -#include <mysql/plugin.h> -#include <mysql/service_wsrep.h> - #ifdef WITH_WSREP #include "dict0priv.h" #include <mysql/service_md5.h> @@ -148,21 +148,6 @@ 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) { - return wsrep_ws_handle_for_trx(wsrep_thd_ws_handle(thd), - (wsrep_trx_id_t)trx->id); -} - -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); -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); #endif /* WITH_WSREP */ /** to force correct commit order in binlog */ @@ -1843,8 +1828,13 @@ thd_to_trx_id( { return(thd_to_trx(thd)->id); } -#endif /* WITH_WSREP */ +static int +wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, + my_bool signal); +static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid); +static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid); +#endif /* WITH_WSREP */ /********************************************************************//** Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth time calls srv_active_wake_master_thread. This function should be used @@ -4161,13 +4151,12 @@ static int innodb_init(void* p) innobase_hton->show_status = innobase_show_status; innobase_hton->flags = HTON_SUPPORTS_EXTENDED_KEYS | HTON_SUPPORTS_FOREIGN_KEYS - | HTON_NATIVE_SYS_VERSIONING; + | HTON_NATIVE_SYS_VERSIONING | HTON_WSREP_REPLICATION; #ifdef WITH_WSREP innobase_hton->abort_transaction=wsrep_abort_transaction; innobase_hton->set_checkpoint=innobase_wsrep_set_checkpoint; innobase_hton->get_checkpoint=innobase_wsrep_get_checkpoint; - innobase_hton->fake_trx_id=wsrep_fake_trx_id; #endif /* WITH_WSREP */ innobase_hton->tablefile_extensions = ha_innobase_exts; @@ -4502,6 +4491,14 @@ innobase_commit_ordered_2( trx->flush_log_later = true; } +#ifdef WITH_WSREP + /* If the transaction is not run in 2pc, we must assign wsrep + XID here in order to get it written in rollback segment. */ + if (wsrep_on(thd)) { + thd_get_xid(thd, (MYSQL_XID*)trx->xid); + } +#endif /* WITH_WSREP */ + innobase_commit_low(trx); if (!read_only) { @@ -4704,6 +4701,15 @@ innobase_rollback( dberr_t error; +#ifdef WITH_WSREP + /* If trx was assigned wsrep XID in prepare phase and the + trx is being rolled back due to BF abort, clear XID in order + to avoid writing it to rollback segment out of order. The XID + will be reassigned when the transaction is replayed. */ + if (wsrep_is_wsrep_xid(trx->xid)) { + trx->xid->null(); + } +#endif /* WITH_WSREP */ if (rollback_trx || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { @@ -5109,7 +5115,7 @@ 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_is_aborting(thd)) { /* if victim has been signaled by BF thread and/or aborting is already progressing, following query aborting is not necessary any more. @@ -8107,9 +8113,9 @@ ha_innobase::write_row( wsrep_thd_query(m_user_thd) : (char *)"void"); error= DB_SUCCESS; - wsrep_thd_set_conflict_state( - m_user_thd, MUST_ABORT); - innobase_srv_conc_exit_innodb(m_prebuilt); + wsrep_thd_self_abort(m_user_thd); + innobase_srv_conc_exit_innodb( + m_prebuilt); /* jump straight to func exit over * later wsrep hooks */ goto func_exit; @@ -8179,10 +8185,14 @@ report_error: #ifdef WITH_WSREP if (!error_result && wsrep_on(m_user_thd) - && wsrep_thd_exec_mode(m_user_thd) == LOCAL_STATE + && wsrep_thd_is_local(m_user_thd) && !wsrep_consistency_check(m_user_thd) - && !wsrep_thd_ignore_table(m_user_thd)) { - if (wsrep_append_keys(m_user_thd, false, record, NULL)) { + && (thd_sql_command(m_user_thd) != SQLCOM_CREATE_TABLE) + && (thd_sql_command(m_user_thd) != SQLCOM_LOAD || + thd_binlog_format(m_user_thd) == BINLOG_FORMAT_ROW)) { + if (wsrep_append_keys(m_user_thd, WSREP_SERVICE_KEY_EXCLUSIVE, + record, + NULL)) { DBUG_PRINT("wsrep", ("row key failed")); error_result = HA_ERR_INTERNAL_ERROR; goto wsrep_error; @@ -8868,13 +8878,17 @@ func_exit: innobase_active_small(); #ifdef WITH_WSREP - if (error == DB_SUCCESS && - wsrep_thd_exec_mode(m_user_thd) == LOCAL_STATE && - wsrep_on(m_user_thd) && - !wsrep_thd_ignore_table(m_user_thd)) { + if (error == DB_SUCCESS + && wsrep_on(m_user_thd) + && wsrep_thd_is_local(m_user_thd)) { + DBUG_PRINT("wsrep", ("update row key")); - if (wsrep_append_keys(m_user_thd, false, old_row, new_row)) { + if (wsrep_append_keys(m_user_thd, + wsrep_protocol_version >= 4 + ? WSREP_SERVICE_KEY_UPDATE + : WSREP_SERVICE_KEY_EXCLUSIVE, + old_row, new_row)){ WSREP_DEBUG("WSREP: UPDATE_ROW_KEY FAILED"); DBUG_PRINT("wsrep", ("row key failed")); err = HA_ERR_INTERNAL_ERROR; @@ -8934,11 +8948,14 @@ ha_innobase::delete_row( innobase_active_small(); #ifdef WITH_WSREP - if (error == DB_SUCCESS && - wsrep_thd_exec_mode(m_user_thd) == LOCAL_STATE && - wsrep_on(m_user_thd) && - !wsrep_thd_ignore_table(m_user_thd)) { - if (wsrep_append_keys(m_user_thd, false, record, NULL)) { + if (error == DB_SUCCESS + && wsrep_on(m_user_thd) + && wsrep_thd_is_local(m_user_thd) + && !wsrep_thd_ignore_table(m_user_thd)) { + + if (wsrep_append_keys(m_user_thd, WSREP_SERVICE_KEY_EXCLUSIVE, + record, + NULL)) { DBUG_PRINT("wsrep", ("delete fail")); error = (dberr_t) HA_ERR_INTERNAL_ERROR; goto wsrep_error; @@ -10121,6 +10138,22 @@ wsrep_dict_foreign_find_index( ibool check_charsets, ulint check_null); +inline +const char* +wsrep_key_type_to_str(Wsrep_service_key_type type) +{ + switch (type) { + case WSREP_SERVICE_KEY_SHARED: + return "shared"; + case WSREP_SERVICE_KEY_REFERENCE: + return "reference"; + case WSREP_SERVICE_KEY_UPDATE: + return "update"; + case WSREP_SERVICE_KEY_EXCLUSIVE: + return "exclusive"; + }; + return "unknown"; +} extern dberr_t wsrep_append_foreign_key( @@ -10130,17 +10163,17 @@ wsrep_append_foreign_key( const rec_t* rec, /*!<in: clustered index record */ dict_index_t* index, /*!<in: clustered index */ ibool referenced, /*!<in: is check for referenced table */ - ibool shared) /*!<in: is shared access */ + Wsrep_service_key_type key_type) /*!< in: access type of this key + (shared, exclusive, reference...) */ { ut_a(trx); THD* thd = (THD*)trx->mysql_thd; ulint rcode = DB_SUCCESS; char cache_key[513] = {'\0'}; int cache_key_len=0; - bool const copy = true; if (!wsrep_on(trx->mysql_thd) || - wsrep_thd_exec_mode(thd) != LOCAL_STATE) { + wsrep_thd_is_local(trx->mysql_thd) == false) { return DB_SUCCESS; } @@ -10230,8 +10263,8 @@ wsrep_append_foreign_key( if (rcode != DB_SUCCESS) { WSREP_ERROR( "FK key set failed: " ULINTPF - " (" ULINTPF " " ULINTPF "), index: %s %s, %s", - rcode, referenced, shared, + " (" ULINTPF "%s), index: %s %s, %s", + rcode, referenced, wsrep_key_type_to_str(key_type), (index) ? index->name() : "void index", (index && index->table) ? index->table->name.m_name : "void table", @@ -10250,7 +10283,7 @@ wsrep_append_foreign_key( #ifdef WSREP_DEBUG_PRINT ulint j; fprintf(stderr, "FK parent key, table: %s %s len: %lu ", - cache_key, (shared) ? "shared" : "exclusive", len+1); + cache_key, wsrep_key_type_to_str(key_type), len+1); for (j=0; j<len+1; j++) { fprintf(stderr, " %hhX, ", key[j]); } @@ -10269,7 +10302,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, @@ -10280,17 +10314,7 @@ wsrep_append_foreign_key( wsrep_thd_query(thd) : "void"); return DB_ERROR; } - - wsrep_t *wsrep= get_wsrep(); - - rcode = (int)wsrep->append_key( - wsrep, - wsrep_ws_handle(thd, trx), - &wkey, - 1, - shared ? WSREP_KEY_SHARED : WSREP_KEY_EXCLUSIVE, - copy); - + rcode = wsrep_thd_append_key(thd, &wkey, 1, key_type); if (rcode) { DBUG_PRINT("wsrep", ("row key failed: " ULINTPF, rcode)); WSREP_ERROR("Appending cascaded fk row key failed: %s, " @@ -10311,16 +10335,19 @@ wsrep_append_key( TABLE_SHARE *table_share, const char* key, uint16_t key_len, - bool shared + Wsrep_service_key_type key_type /*!< in: access type of this key + (shared, exclusive, semi...) */ ) { DBUG_ENTER("wsrep_append_key"); - bool const copy = true; + DBUG_PRINT("enter", + ("thd: %lu trx: %lld", thd_get_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", - thd_get_thread_id(thd), (long long)trx->id, key_len, - table_share->table_name.str, wsrep_thd_query(thd)); + fprintf(stderr, "%s conn %lu, trx " TRX_ID_FMT ", keylen %d, key %s.%s\n", + wsrep_key_type_to_str(key_type), + thd_get_thread_id(thd), trx->id, key_len, + table_share->table_name.str, key); for (int i=0; i<key_len; i++) { fprintf(stderr, "%hhX, ", key[i]); } @@ -10329,7 +10356,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, @@ -10341,15 +10369,7 @@ wsrep_append_key( DBUG_RETURN(HA_ERR_INTERNAL_ERROR); } - wsrep_t *wsrep= get_wsrep(); - - int rcode = (int)wsrep->append_key( - wsrep, - wsrep_ws_handle(thd, trx), - &wkey, - 1, - shared ? WSREP_KEY_SHARED : WSREP_KEY_EXCLUSIVE, - copy); + int rcode = wsrep_thd_append_key(thd, &wkey, 1, key_type); if (rcode) { DBUG_PRINT("wsrep", ("row key failed: %d", rcode)); WSREP_WARN("Appending row key failed: %s, %d", @@ -10390,16 +10410,30 @@ int ha_innobase::wsrep_append_keys( /*===========================*/ THD *thd, - bool shared, + Wsrep_service_key_type key_type, /*!< in: access type of this row + operation: + (shared, exclusive, reference...) */ const uchar* record0, /* in: row in MySQL format */ const uchar* record1) /* in: row in MySQL format */ { + /* Sanity check: newly inserted records should always be passed with + EXCLUSIVE key type, all the rest are expected to carry a pre-image + */ + ut_a(record1 != NULL || key_type == WSREP_SERVICE_KEY_EXCLUSIVE); + int rcode; DBUG_ENTER("wsrep_append_keys"); bool key_appended = false; trx_t *trx = thd_to_trx(thd); +#ifdef WSREP_DEBUG_PRINT + fprintf(stderr, "%s conn %lu, trx " TRX_ID_FMT ", table %s\nSQL: %s\n", + wsrep_key_type_to_str(key_type), + thd_get_thread_id(thd), trx->id, + table_share->table_name.str, wsrep_thd_query(thd)); +#endif + if (table_share && table_share->tmp_table != NO_TMP_TABLE) { WSREP_DEBUG("skipping tmp table DML: THD: %lu tmp: %d SQL: %s", thd_get_thread_id(thd), @@ -10422,7 +10456,7 @@ ha_innobase::wsrep_append_keys( if (!is_null) { rcode = wsrep_append_key( thd, trx, table_share, keyval, - len, shared); + len, key_type); if (rcode) { DBUG_RETURN(rcode); @@ -10440,68 +10474,91 @@ ha_innobase::wsrep_append_keys( KEY* key_info = table->key_info + i; if (key_info->flags & HA_NOSAME) { hasPK = true; + break; } } for (i=0; i<table->s->keys; ++i) { - uint len; - char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; - char keyval1[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; - char* key0 = &keyval0[1]; - char* key1 = &keyval1[1]; KEY* key_info = table->key_info + i; - ibool is_null; dict_index_t* idx = innobase_get_index(i); dict_table_t* tab = (idx) ? idx->table : NULL; + /* keyval[] shall contain an ordinal number at byte 0 + and the actual key data shall be written at byte 1. + Hence the total data length is the key length + 1 */ + char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; + char keyval1[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; keyval0[0] = (char)i; keyval1[0] = (char)i; + char* key0 = &keyval0[1]; + char* key1 = &keyval1[1]; if (!tab) { WSREP_WARN("MariaDB-InnoDB key mismatch %s %s", table->s->table_name.str, key_info->name.str); } - /* !hasPK == table with no PK, must append all non-unique keys */ + /* !hasPK == table with no PK, + must append all non-unique keys */ if (!hasPK || key_info->flags & HA_NOSAME || ((tab && referenced_by_foreign_key2(tab, idx)) || (!tab && referenced_by_foreign_key()))) { - len = wsrep_store_key_val_for_row( + ibool is_null0; + uint len0 = wsrep_store_key_val_for_row( thd, table, i, key0, WSREP_MAX_SUPPORTED_KEY_LENGTH, - record0, &is_null); - if (!is_null) { - rcode = wsrep_append_key( - thd, trx, table_share, - keyval0, len+1, shared); - - if (rcode) { - DBUG_RETURN(rcode); - } - - if (key_info->flags & HA_NOSAME || shared) - key_appended = true; - } else { - WSREP_DEBUG("NULL key skipped: %s", - wsrep_thd_query(thd)); - } + record0, &is_null0); if (record1) { - len = wsrep_store_key_val_for_row( + ibool is_null1; + uint len1 = wsrep_store_key_val_for_row( thd, table, i, key1, WSREP_MAX_SUPPORTED_KEY_LENGTH, - record1, &is_null); + record1, &is_null1); + + if (is_null0 != is_null1 || + len0 != len1 || + memcmp(key0, key1, len0)) { + /* This key has chaged. If it + is unique, this is an exclusive + operation -> upgrade key type */ + if (key_info->flags & HA_NOSAME) { + key_type = WSREP_SERVICE_KEY_EXCLUSIVE; + } - if (!is_null && memcmp(key0, key1, len)) { - rcode = wsrep_append_key( + if (!is_null1) { + rcode = wsrep_append_key( thd, trx, table_share, - keyval1, len+1, shared); - if (rcode) DBUG_RETURN(rcode); + keyval1, + /* for len1+1 see keyval1 + initialization comment */ + len1+1, key_type); + if (rcode) + DBUG_RETURN(rcode); + } } } + + if (!is_null0) { + rcode = wsrep_append_key( + thd, trx, table_share, + /* for len0+1 see keyval0 + initialization comment */ + keyval0, len0+1, key_type); + if (rcode) + DBUG_RETURN(rcode); + + if (key_info->flags & HA_NOSAME || + key_type == WSREP_SERVICE_KEY_SHARED|| + key_type == WSREP_SERVICE_KEY_REFERENCE) + key_appended = true; + } else { + WSREP_DEBUG("NULL key skipped: %s", + wsrep_thd_query(thd)); + } } } } @@ -10515,7 +10572,7 @@ ha_innobase::wsrep_append_keys( if ((rcode = wsrep_append_key(thd, trx, table_share, (const char*) digest, 16, - shared))) { + key_type))) { DBUG_RETURN(rcode); } @@ -10524,7 +10581,7 @@ ha_innobase::wsrep_append_keys( digest, record1, table, m_prebuilt); if ((rcode = wsrep_append_key(thd, trx, table_share, (const char*) digest, - 16, shared))) { + 16, key_type))) { DBUG_RETURN(rcode); } } @@ -15405,8 +15462,7 @@ ha_innobase::external_lock( if (!skip) { #ifdef WITH_WSREP - if (!wsrep_on(thd) || wsrep_thd_exec_mode(thd) == LOCAL_STATE) - { + if (!wsrep_on(thd) || wsrep_thd_is_local(m_user_thd)) { #endif /* WITH_WSREP */ my_error(ER_BINLOG_STMT_MODE_AND_ROW_ENGINE, MYF(0), " InnoDB is limited to row-logging when" @@ -16920,6 +16976,14 @@ innobase_rollback_by_xid( } if (trx_t* trx = trx_get_trx_by_xid(xid)) { +#ifdef WITH_WSREP + /* If a wsrep transaction is being rolled back during + the recovery, we must clear the xid in order to avoid + writing serialisation history for rolled back transaction. */ + if (wsrep_is_wsrep_xid(trx->xid)) { + trx->xid->null(); + } +#endif /* WITH_WSREP */ int ret = innobase_rollback_trx(trx); trx_deregister_from_2pc(trx); ut_ad(!trx->will_lock); @@ -18520,123 +18584,32 @@ wsrep_innobase_kill_one_trx( bf_trx ? bf_trx->id : 0); DBUG_RETURN(1); } - 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, thd_get_thread_id(thd), victim_trx->id); - WSREP_DEBUG("Aborting query: %s conf %d trx: %" PRId64, + WSREP_DEBUG("Aborting query: %s conf %s trx: %lld", (thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void", - 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); - - victim_trx->lock.was_chosen_as_deadlock_victim= TRUE; - + wsrep_thd_transaction_state_str(thd), + wsrep_thd_transaction_id(thd)); + + /* + * we mark with was_chosen_as_deadlock_victim transaction, + * which is already marked as BF victim + * lock_sys is held until this vicitm has aborted + */ + victim_trx->lock.was_chosen_as_wsrep_victim = TRUE; + + wsrep_thd_UNLOCK(thd); + if (wsrep_thd_bf_abort(bf_thd, thd, signal)) + { if (victim_trx->lock.wait_lock) { - WSREP_DEBUG("victim has wait flag: %ld", - thd_get_thread_id(thd)); + WSREP_DEBUG("victim has wait flag: %lu", + thd_get_thread_id(thd)); lock_t* wait_lock = victim_trx->lock.wait_lock; if (wait_lock) { @@ -18644,67 +18617,7 @@ 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); - } else { - /* abort currently executing query */ - DBUG_PRINT("wsrep",("sending KILL_QUERY to: %lu", - thd_get_thread_id(thd))); - WSREP_DEBUG("kill query for: %ld", - thd_get_thread_id(thd)); - /* Note that innobase_kill_query will take lock_mutex - and trx_mutex */ - wsrep_thd_UNLOCK(thd); - wsrep_thd_awake(thd, signal); - - /* for BF thd, we need to prevent him from committing */ - if (wsrep_thd_exec_mode(thd) == REPL_RECV) { - wsrep_abort_slave_trx(bf_seqno, - 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)); - wsrep_thd_UNLOCK(thd); - break; } DBUG_RETURN(0); @@ -18724,26 +18637,22 @@ wsrep_abort_transaction( trx_t* victim_trx = thd_to_trx(victim_thd); trx_t* bf_trx = (bf_thd) ? thd_to_trx(bf_thd) : NULL; - WSREP_DEBUG("abort transaction: BF: %s victim: %s victim conf: %d", + WSREP_DEBUG("abort transaction: BF: %s victim: %s victim conf: %s", wsrep_thd_query(bf_thd), wsrep_thd_query(victim_thd), - wsrep_thd_conflict_state(victim_thd, FALSE)); + wsrep_thd_transaction_state_str(victim_thd)); if (victim_trx) { lock_mutex_enter(); trx_mutex_enter(victim_trx); - int rcode = wsrep_innobase_kill_one_trx(bf_thd, bf_trx, - victim_trx, signal); - lock_mutex_exit(); + int rcode= wsrep_innobase_kill_one_trx(bf_thd, bf_trx, + victim_trx, signal); trx_mutex_exit(victim_trx); + lock_mutex_exit(); wsrep_srv_conc_cancel_wait(victim_trx); DBUG_RETURN(rcode); } else { - WSREP_DEBUG("victim does not have transaction"); - wsrep_thd_LOCK(victim_thd); - wsrep_thd_set_conflict_state(victim_thd, MUST_ABORT); - wsrep_thd_UNLOCK(victim_thd); - wsrep_thd_awake(victim_thd, signal); + wsrep_thd_bf_abort(bf_thd, victim_thd, signal); } DBUG_RETURN(-1); @@ -18779,15 +18688,6 @@ innobase_wsrep_get_checkpoint( trx_rseg_read_wsrep_checkpoint(*xid); return 0; } - -static void wsrep_fake_trx_id(handlerton *, THD *thd) -{ - trx_id_t trx_id = trx_sys.get_new_trx_id(); - WSREP_DEBUG("innodb fake trx id: " TRX_ID_FMT " thd: %s", - trx_id, wsrep_thd_query(thd)); - wsrep_ws_handle_for_trx(wsrep_thd_ws_handle(thd), trx_id); -} - #endif /* WITH_WSREP */ /* plugin options */ diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 6f0c5b535fb..71212785df4 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -16,6 +16,10 @@ this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ +#ifdef WITH_WSREP +#include "wsrep_api.h" +#include <mysql/service_wsrep.h> +#endif /* WITH_WSREP */ /* The InnoDB handler: the interface between MySQL and InnoDB. */ @@ -444,8 +448,11 @@ protected: dict_index_t* innobase_get_index(uint keynr); #ifdef WITH_WSREP - int wsrep_append_keys(THD *thd, bool shared, - const uchar* record0, const uchar* record1); + int wsrep_append_keys( + THD *thd, + Wsrep_service_key_type key_type, + const uchar* record0, + const uchar* record1); #endif /** Builds a 'template' to the prebuilt struct. @@ -571,23 +578,7 @@ 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); - -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); - -extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id); - -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" 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 /* WITH_WSREP */ extern const struct _ft_vft ft_vft_result; @@ -621,10 +612,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/trx0trx.h b/storage/innobase/include/trx0trx.h index 34d61100a9b..8bf64c28441 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -577,6 +577,11 @@ struct trx_lock_t { lock_sys.mutex. Otherwise, this may only be modified by the thread that is serving the running transaction. */ +#ifdef WITH_WSREP + bool was_chosen_as_wsrep_victim; + /*!< high priority wsrep thread has + marked this trx to abort */ +#endif /* WITH_WSREP */ /** Pre-allocated record locks */ struct { diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 7fc986bdbca..493f73cc148 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -762,9 +762,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 @@ -774,12 +772,11 @@ lock_rec_has_to_wait( << type_mode << " supremum: " << lock_is_on_supremum << "conflicts states: my " - << wsrep_thd_conflict_state( - trx->mysql_thd, FALSE) + << wsrep_thd_transaction_state_str( + trx->mysql_thd) << " locked " - << wsrep_thd_conflict_state( - lock2->trx->mysql_thd, - FALSE); + << wsrep_thd_transaction_state_str( + lock2->trx->mysql_thd); lock_rec_print(stderr, lock2); ib::info() << " SQL1: " << wsrep_thd_query(trx->mysql_thd) @@ -1098,11 +1095,14 @@ wsrep_kill_victim( return; } - my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE); + if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { + 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( + if ((!bf_other) || + (wsrep_thd_order_before( trx->mysql_thd, lock->trx->mysql_thd))) { if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) { @@ -1113,11 +1113,7 @@ wsrep_kill_victim( is in the queue*/ } else if (lock->trx != trx) { if (wsrep_log_conflicts) { - if (bf_this) { - ib::info() << "*** Priority TRANSACTION:"; - } else { - ib::info() << "*** Victim TRANSACTION:"; - } + ib::info() << "*** Priority TRANSACTION:"; trx_print_latched(stderr, trx, 3000); @@ -1426,7 +1422,7 @@ lock_rec_create_low( lock_t *prev = NULL; while (hash && wsrep_thd_is_BF(hash->trx->mysql_thd, TRUE) - && wsrep_trx_order_before(hash->trx->mysql_thd, + && wsrep_thd_order_before(hash->trx->mysql_thd, trx->mysql_thd)) { prev = hash; hash = (lock_t *)hash->hash; @@ -1840,15 +1836,15 @@ lock_rec_add_to_queue( ib::info() << "WSREP BF lock conflict for my lock:\n BF:" << ((wsrep_thd_is_BF(trx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " << - wsrep_thd_exec_mode(trx->mysql_thd) << " conflict: " << - wsrep_thd_conflict_state(trx->mysql_thd, false) << " seqno: " << + wsrep_thd_client_state_str(trx->mysql_thd) << " conflict: " << + wsrep_thd_transaction_state_str(trx->mysql_thd) << " seqno: " << wsrep_thd_trx_seqno(trx->mysql_thd) << " SQL: " << wsrep_thd_query(trx->mysql_thd); trx_t* otrx = other_lock->trx; ib::info() << "WSREP other lock:\n BF:" << ((wsrep_thd_is_BF(otrx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " << - wsrep_thd_exec_mode(otrx->mysql_thd) << " conflict: " << - wsrep_thd_conflict_state(otrx->mysql_thd, false) << " seqno: " << + wsrep_thd_client_state_str(otrx->mysql_thd) << " conflict: " << + wsrep_thd_transaction_state_str(otrx->mysql_thd) << " seqno: " << wsrep_thd_trx_seqno(otrx->mysql_thd) << " SQL: " << wsrep_thd_query(otrx->mysql_thd); } @@ -4949,8 +4945,8 @@ lock_rec_queue_validate( if (!lock_get_wait(other_lock) ) { ib::info() << "WSREP impl BF lock conflict for my impl lock:\n BF:" << ((wsrep_thd_is_BF(impl_trx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " << - wsrep_thd_exec_mode(impl_trx->mysql_thd) << " conflict: " << - wsrep_thd_conflict_state(impl_trx->mysql_thd, false) << " seqno: " << + wsrep_thd_client_state_str(impl_trx->mysql_thd) << " conflict: " << + wsrep_thd_transaction_state_str(impl_trx->mysql_thd) << " seqno: " << wsrep_thd_trx_seqno(impl_trx->mysql_thd) << " SQL: " << wsrep_thd_query(impl_trx->mysql_thd); @@ -4958,8 +4954,8 @@ lock_rec_queue_validate( ib::info() << "WSREP other lock:\n BF:" << ((wsrep_thd_is_BF(otrx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " << - wsrep_thd_exec_mode(otrx->mysql_thd) << " conflict: " << - wsrep_thd_conflict_state(otrx->mysql_thd, false) << " seqno: " << + wsrep_thd_client_state_str(otrx->mysql_thd) << " conflict: " << + wsrep_thd_transaction_state_str(otrx->mysql_thd) << " seqno: " << wsrep_thd_trx_seqno(otrx->mysql_thd) << " SQL: " << wsrep_thd_query(otrx->mysql_thd); } @@ -6395,6 +6391,12 @@ lock_trx_handle_wait( /*=================*/ trx_t* trx) /*!< in/out: trx lock state */ { +#ifdef WITH_WSREP + /* We already own mutexes */ + if (trx->lock.was_chosen_as_wsrep_victim) { + return lock_trx_handle_wait_low(trx); + } +#endif /* WITH_WSREP */ lock_mutex_enter(); trx_mutex_enter(trx); dberr_t err = lock_trx_handle_wait_low(trx); @@ -6992,6 +6994,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/row/row0ins.cc b/storage/innobase/row/row0ins.cc index e2ac60c1103..ed72f6d482b 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -44,6 +44,9 @@ Created 4/20/1996 Heikki Tuuri #include "buf0lru.h" #include "fts0fts.h" #include "fts0types.h" +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#endif /* WITH_WSREP */ /************************************************************************* IMPORTANT NOTE: Any operation that generates redo MUST check that there @@ -1043,7 +1046,7 @@ dberr_t wsrep_append_foreign_key(trx_t *trx, const rec_t* clust_rec, dict_index_t* clust_index, ibool referenced, - ibool shared); + Wsrep_service_key_type key_type); #endif /* WITH_WSREP */ /*********************************************************************//** @@ -1430,7 +1433,7 @@ row_ins_foreign_check_on_constraint( #ifdef WITH_WSREP err = wsrep_append_foreign_key(trx, foreign, clust_rec, clust_index, - FALSE, FALSE); + FALSE, WSREP_SERVICE_KEY_EXCLUSIVE); if (err != DB_SUCCESS) { fprintf(stderr, "WSREP: foreign key append failed: %d\n", err); @@ -1811,7 +1814,10 @@ row_ins_check_foreign_constraint( rec, check_index, check_ref, - (upd_node) ? TRUE : FALSE); + (upd_node != NULL + && wsrep_protocol_version < 4) + ? WSREP_SERVICE_KEY_SHARED + : WSREP_SERVICE_KEY_REFERENCE); #endif /* WITH_WSREP */ goto end_scan; } else if (foreign->type != 0) { @@ -3228,9 +3234,27 @@ 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 = index->table->no_rollback() ? BTR_NO_ROLLBACK + : (index->table->is_temporary() || skip_locking) + ? BTR_NO_LOCKING_FLAG : 0; +#ifdef UNIV_DEBUG + if (skip_locking && strcmp(wsrep_get_sr_table_name(), + index->table->name.m_name)) { + WSREP_ERROR("Record locking is disabled in this thread, " + "but the table being modified is not " + "`%s`: `%s`.", wsrep_get_sr_table_name(), + 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 658785a5c03..8d7824bfc56 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -54,6 +54,9 @@ Created 12/19/1997 Heikki Tuuri #include "buf0lru.h" #include "srv0srv.h" #include "srv0mon.h" +#ifdef WITH_WSREP +#include "mysql/service_wsrep.h" /* For wsrep_thd_skip_locking */ +#endif /* Maximum number of rows to prefetch; MySQL interface has another parameter */ #define SEL_MAX_N_PREFETCH 16 @@ -4442,6 +4445,13 @@ row_search_mvcc( set_also_gap_locks = FALSE; } +#ifdef WITH_WSREP + else if (wsrep_thd_skip_locking(trx->mysql_thd)) { + ut_ad(!strcmp(wsrep_get_sr_table_name(), + 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 591ae238c43..a60210c77c8 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -2458,7 +2458,7 @@ row_upd_sec_index_entry( err = DB_SUCCESS; break; case DB_DEADLOCK: - if (wsrep_debug) { + if (wsrep_get_debug()) { ib::warn() << "WSREP: sec index FK check fail for deadlock" << " index " << index->name << " table " << index->table->name; @@ -2773,7 +2773,7 @@ check_fk: err = DB_SUCCESS; break; case DB_DEADLOCK: - if (wsrep_debug) { + if (wsrep_get_debug()) { ib::warn() << "WSREP: sec index FK check fail for deadlock" << " index " << index->name << " table " << index->table->name; @@ -3002,7 +3002,7 @@ row_upd_del_mark_clust_rec( err = DB_SUCCESS; break; case DB_DEADLOCK: - if (wsrep_debug) { + if (wsrep_get_debug()) { ib::warn() << "WSREP: sec index FK check fail for deadlock" << " index " << index->name << " table " << index->table->name; diff --git a/storage/innobase/srv/srv0conc.cc b/storage/innobase/srv/srv0conc.cc index 6beeee58fae..b2b464e31fa 100644 --- a/storage/innobase/srv/srv0conc.cc +++ b/storage/innobase/srv/srv0conc.cc @@ -119,8 +119,8 @@ srv_conc_enter_innodb_with_atomics( ulint sleep_in_us; #ifdef WITH_WSREP if (wsrep_on(trx->mysql_thd) && - wsrep_trx_is_aborting(trx->mysql_thd)) { - if (wsrep_debug) { + wsrep_thd_is_aborting(trx->mysql_thd)) { + if (wsrep_get_debug()) { ib::info() << "srv_conc_enter due to MUST_ABORT"; } @@ -308,14 +308,14 @@ wsrep_srv_conc_cancel_wait( srv_conc_enter_innodb_with_atomics(). No need to cancel here, thr will wake up after os_sleep and let to enter innodb */ - if (wsrep_debug) { + if (wsrep_get_debug()) { ib::info() << "WSREP: conc slot cancel, no atomics"; } #else // JAN: TODO: MySQL 5.7 //os_fast_mutex_lock(&srv_conc_mutex); if (trx->wsrep_event) { - if (wsrep_debug) { + if (wsrep_get_debug()) { ib::info() << "WSREP: conc slot cancel"; } os_event_set(trx->wsrep_event); diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 890bd969670..3b5461aae25 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -76,10 +76,6 @@ Created 10/8/1995 Heikki Tuuri #include <my_service_manager.h> -#ifdef WITH_WSREP -extern int wsrep_debug; -extern int wsrep_trx_is_aborting(void *thd_ptr); -#endif /* The following is the maximum allowed duration of a lock wait. */ UNIV_INTERN ulong srv_fatal_semaphore_wait_threshold = DEFAULT_SRV_FATAL_SEMAPHORE_TIMEOUT; diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 54b0e75fd80..e15afcf9cd7 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -2328,7 +2328,7 @@ files_checked: Create the dump/load thread only when not running with --wsrep-recover. */ - if (!wsrep_recovery) { + if (!get_wsrep_recovery()) { #endif /* WITH_WSREP */ /* Create the buffer pool dump/load thread */ diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index 4b0684d1735..22b72a14304 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -178,6 +178,11 @@ trx_rollback_to_savepoint( partial rollback requested, or NULL for complete rollback */ { +#ifdef WITH_WSREP + if (savept == NULL && wsrep_on(trx->mysql_thd)) { + 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); @@ -446,12 +451,8 @@ trx_rollback_to_savepoint_for_mysql_low( trx_mark_sql_stat_end(trx); trx->op_info = ""; - #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && - trx->lock.was_chosen_as_deadlock_victim) { - trx->lock.was_chosen_as_deadlock_victim = FALSE; - } + trx->lock.was_chosen_as_wsrep_victim = FALSE; #endif return(err); } diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc index f0793140277..239df440c2b 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -43,6 +43,33 @@ static long long wsrep_seqno = -1; /** The latest known WSREP XID UUID */ static unsigned char wsrep_uuid[16]; +/** Write the WSREP XID information into rollback segment header. +@param[in,out] rseg_header rollback segment header +@param[in] xid WSREP XID +@param[in,out] mtr mini transaction */ +static void +trx_rseg_write_wsrep_checkpoint( + trx_rsegf_t* rseg_header, + const XID* xid, + mtr_t* mtr) +{ + mlog_write_ulint(TRX_RSEG_WSREP_XID_FORMAT + rseg_header, + uint32_t(xid->formatID), + MLOG_4BYTES, mtr); + + mlog_write_ulint(TRX_RSEG_WSREP_XID_GTRID_LEN + rseg_header, + uint32_t(xid->gtrid_length), + MLOG_4BYTES, mtr); + + mlog_write_ulint(TRX_RSEG_WSREP_XID_BQUAL_LEN + rseg_header, + uint32_t(xid->bqual_length), + MLOG_4BYTES, mtr); + + mlog_write_string(TRX_RSEG_WSREP_XID_DATA + rseg_header, + reinterpret_cast<const byte*>(xid->data), + XIDDATASIZE, mtr); +} + /** Update the WSREP XID information in rollback segment header. @param[in,out] rseg_header rollback segment header @param[in] xid WSREP XID @@ -60,29 +87,15 @@ 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 (xid_seqno != -1 + && !memcmp(xid_uuid, wsrep_uuid, sizeof wsrep_uuid)) { ut_ad(xid_seqno > wsrep_seqno); } else { memcpy(wsrep_uuid, xid_uuid, sizeof wsrep_uuid); } wsrep_seqno = xid_seqno; #endif /* UNIV_DEBUG */ - - mlog_write_ulint(TRX_RSEG_WSREP_XID_FORMAT + rseg_header, - uint32_t(xid->formatID), - MLOG_4BYTES, mtr); - - mlog_write_ulint(TRX_RSEG_WSREP_XID_GTRID_LEN + rseg_header, - uint32_t(xid->gtrid_length), - MLOG_4BYTES, mtr); - - mlog_write_ulint(TRX_RSEG_WSREP_XID_BQUAL_LEN + rseg_header, - uint32_t(xid->bqual_length), - MLOG_4BYTES, mtr); - - mlog_write_string(TRX_RSEG_WSREP_XID_DATA + rseg_header, - reinterpret_cast<const byte*>(xid->data), - XIDDATASIZE, mtr); + trx_rseg_write_wsrep_checkpoint(rseg_header, xid, mtr); } /** Update WSREP checkpoint XID in first rollback segment header @@ -97,6 +110,13 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid) mtr_t mtr; mtr.start(); + const byte* xid_uuid = wsrep_xid_uuid(xid); + /* We must make check against wsrep_uuid here, the + trx_rseg_update_wsrep_checkpoint() writes over wsrep_uuid with + xid contents in debug mode and the memcmp() will never give nonzero + result. */ + const bool must_clear_rsegs = memcmp(wsrep_uuid, xid_uuid, + sizeof wsrep_uuid); const trx_rseg_t* rseg = trx_sys.rseg_array[0]; trx_rsegf_t* rseg_header = trx_rsegf_get(rseg->space, rseg->page_no, @@ -107,10 +127,11 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid) trx_rseg_update_wsrep_checkpoint(rseg_header, xid, &mtr); - const byte* xid_uuid = wsrep_xid_uuid(xid); - if (memcmp(wsrep_uuid, xid_uuid, sizeof wsrep_uuid)) { + if (must_clear_rsegs) { + XID null_xid; + memset(&null_xid, 0, sizeof null_xid); + null_xid.null(); memcpy(wsrep_uuid, xid_uuid, sizeof wsrep_uuid); - /* Because the UUID part of the WSREP XID differed from current_xid_uuid, the WSREP group UUID was changed, and we must reset the XID in all rollback @@ -118,10 +139,12 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid) for (ulint rseg_id = 1; rseg_id < TRX_SYS_N_RSEGS; ++rseg_id) { if (const trx_rseg_t* rseg = trx_sys.rseg_array[rseg_id]) { - trx_rseg_update_wsrep_checkpoint( + trx_rseg_write_wsrep_checkpoint( trx_rsegf_get(rseg->space, - rseg->page_no, &mtr), - xid, &mtr); + rseg->page_no, + &mtr), + &null_xid, + &mtr); } } } diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 333c7fe90eb..7be760c6221 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -1441,11 +1441,8 @@ trx_commit_in_memory( trx_mutex_enter(trx); trx->dict_operation = TRX_DICT_OP_NONE; - #ifdef WITH_WSREP - if (trx->mysql_thd && wsrep_on(trx->mysql_thd)) { - trx->lock.was_chosen_as_deadlock_victim = FALSE; - } + trx->lock.was_chosen_as_wsrep_victim = FALSE; #endif DBUG_LOG("trx", "Commit in memory: " << trx); @@ -2155,7 +2152,7 @@ static my_bool trx_get_trx_by_xid_callback(rw_trx_hash_element_t *element, transaction needs a valid trx->xid for invoking trx_sys_update_wsrep_checkpoint(). */ if (!wsrep_is_wsrep_xid(trx->xid)) -#endif +#endif /* WITH_WSREP */ /* Invalidate the XID, so that subsequent calls will not find it. */ trx->xid->null(); arg->trx= trx; diff --git a/support-files/compiler_warnings.supp b/support-files/compiler_warnings.supp index 4d9ca1c815b..3f7a79556f9 100644 --- a/support-files/compiler_warnings.supp +++ b/support-files/compiler_warnings.supp @@ -204,7 +204,6 @@ .*/ctype-simple\.c : .*unary minus operator applied to unsigned type, result still unsigned.* .*/sql/sys_vars\.cc : invalid access to non-static data member .*/string3\.h : memset used with constant zero length parameter -.*/sql/wsrep_hton\.cc : NULL used in arithmetic : 500-600 .* : missing-declarations.*is valid # diff --git a/wsrep-lib b/wsrep-lib new file mode 160000 +Subproject 8e4777114b92f4d86000d69603c66ec49ca41b9 diff --git a/wsrep/CMakeLists.txt b/wsrep/CMakeLists.txt deleted file mode 100644 index ff2bdec4def..00000000000 --- a/wsrep/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (c) 2012, Codership Oy. 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 - -SET(WSREP_SOURCES wsrep_gtid.c wsrep_uuid.c wsrep_loader.c wsrep_dummy.c) - -IF(NOT WITH_INNOBASE_STORAGE_ENGINE) - MESSAGE(WARNING "WSRep is enabled, but innodb is not. This configuration is not supported") -ENDIF() - -ADD_CONVENIENCE_LIBRARY(wsrep ${WSREP_SOURCES}) -DTRACE_INSTRUMENT(wsrep) - -#ADD_EXECUTABLE(listener wsrep_listener.c ${WSREP_SOURCES}) -#TARGET_LINK_LIBRARIES(listener ${LIBDL}) diff --git a/wsrep/wsrep_api.h b/wsrep/wsrep_api.h deleted file mode 100644 index 1d6bc059d3d..00000000000 --- a/wsrep/wsrep_api.h +++ /dev/null @@ -1,1117 +0,0 @@ -/* Copyright (C) 2009-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. - */ - -/*! - @file wsrep API declaration. - - HOW TO READ THIS FILE. - - Due to C language rules this header layout doesn't lend itself to intuitive - reading. So here's the scoop: in the end this header declares two main types: - - * struct wsrep_init_args - - and - - * struct wsrep - - wsrep_init_args contains initialization parameters for wsrep provider like - names, addresses, etc. and pointers to callbacks. The callbacks will be called - by provider when it needs to do something application-specific, like log a - message or apply a writeset. It should be passed to init() call from - wsrep API. It is an application part of wsrep API contract. - - struct wsrep is the interface to wsrep provider. It contains all wsrep API - calls. It is a provider part of wsrep API contract. - - Finally, wsrep_load() method loads (dlopens) wsrep provider library. It is - defined in wsrep_loader.c unit and is part of libwsrep.a (which is not a - wsrep provider, but a convenience library). - - wsrep_unload() does the reverse. - -*/ -#ifndef WSREP_H -#define WSREP_H - -#include <stdint.h> -#include <stdlib.h> -#include <unistd.h> -#include <time.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/************************************************************************** - * * - * wsrep replication API * - * * - **************************************************************************/ - -#define WSREP_INTERFACE_VERSION "25" - -/*! Empty backend spec */ -#define WSREP_NONE "none" - - -/*! - * @brief log severity levels, passed as first argument to log handler - */ -typedef enum wsrep_log_level -{ - WSREP_LOG_FATAL, //!< Unrecoverable error, application must quit. - WSREP_LOG_ERROR, //!< Operation failed, must be repeated. - WSREP_LOG_WARN, //!< Unexpected condition, but no operational failure. - WSREP_LOG_INFO, //!< Informational message. - WSREP_LOG_DEBUG //!< Debug message. Shows only of compiled with debug. -} wsrep_log_level_t; - -/*! - * @brief error log handler - * - * All messages from wsrep provider are directed to this - * handler, if present. - * - * @param level log level - * @param message log message - */ -typedef void (*wsrep_log_cb_t)(wsrep_log_level_t, const char *); - - -/*! - * Certain provider capabilities application may want to know about - */ -#define WSREP_CAP_MULTI_MASTER ( 1ULL << 0 ) -#define WSREP_CAP_CERTIFICATION ( 1ULL << 1 ) -#define WSREP_CAP_PARALLEL_APPLYING ( 1ULL << 2 ) -#define WSREP_CAP_TRX_REPLAY ( 1ULL << 3 ) -#define WSREP_CAP_ISOLATION ( 1ULL << 4 ) -#define WSREP_CAP_PAUSE ( 1ULL << 5 ) -#define WSREP_CAP_CAUSAL_READS ( 1ULL << 6 ) -#define WSREP_CAP_CAUSAL_TRX ( 1ULL << 7 ) -#define WSREP_CAP_INCREMENTAL_WRITESET ( 1ULL << 8 ) -#define WSREP_CAP_SESSION_LOCKS ( 1ULL << 9 ) -#define WSREP_CAP_DISTRIBUTED_LOCKS ( 1ULL << 10 ) -#define WSREP_CAP_CONSISTENCY_CHECK ( 1ULL << 11 ) -#define WSREP_CAP_UNORDERED ( 1ULL << 12 ) -#define WSREP_CAP_ANNOTATION ( 1ULL << 13 ) -#define WSREP_CAP_PREORDERED ( 1ULL << 14 ) - - -/*! - * Writeset flags - * - * COMMIT 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 - * ROLLBACK). - */ -#define WSREP_FLAG_COMMIT ( 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 ) - - -typedef uint64_t wsrep_trx_id_t; //!< application transaction ID -typedef uint64_t wsrep_conn_id_t; //!< application connection ID -typedef int64_t wsrep_seqno_t; //!< sequence number of a writeset, etc. -#ifdef __cplusplus -typedef bool wsrep_bool_t; -#else -typedef _Bool wsrep_bool_t; //!< should be the same as standard (C99) bool -#endif /* __cplusplus */ - -/*! undefined seqno */ -#define WSREP_SEQNO_UNDEFINED (-1) - - -/*! wsrep provider status codes */ -typedef enum wsrep_status -{ - WSREP_OK = 0, //!< success - WSREP_WARNING, //!< minor warning, error logged - WSREP_TRX_MISSING, //!< transaction is not known by wsrep - WSREP_TRX_FAIL, //!< transaction aborted, server can continue - WSREP_BF_ABORT, //!< trx was victim of brute force abort - WSREP_SIZE_EXCEEDED, //!< data exceeded maximum supported size - 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_status_t; - - -/*! wsrep callbacks status codes */ -typedef enum wsrep_cb_status -{ - WSREP_CB_SUCCESS = 0, //!< success (as in "not critical failure") - WSREP_CB_FAILURE //!< critical failure (consistency violation) - /* Technically, wsrep provider has no use for specific failure codes since - * there is nothing it can do about it but abort execution. Therefore any - * positive number shall indicate a critical failure. Optionally that value - * may be used by provider to come to a consensus about state consistency - * in a group of nodes. */ -} wsrep_cb_status_t; - - -/*! - * UUID type - for all unique IDs - */ -typedef struct wsrep_uuid { - uint8_t data[16]; -} wsrep_uuid_t; - -/*! Undefined UUID */ -static const wsrep_uuid_t WSREP_UUID_UNDEFINED = {{0,}}; - -/*! UUID string representation length, terminating '\0' not included */ -#define WSREP_UUID_STR_LEN 36 - -/*! - * Scan UUID from string - * @return length of UUID string representation or negative error code - */ -extern int -wsrep_uuid_scan (const char* str, size_t str_len, wsrep_uuid_t* uuid); - -/*! - * Print UUID to string - * @return length of UUID string representation or negative error code - */ -extern int -wsrep_uuid_print (const wsrep_uuid_t* uuid, char* str, size_t str_len); - -#define WSREP_MEMBER_NAME_LEN 32 //!< maximum logical member name length -#define WSREP_INCOMING_LEN 256 //!< max Domain Name length + 0x00 - - -/*! - * Global transaction identifier - */ -typedef struct wsrep_gtid -{ - wsrep_uuid_t uuid; /*!< History UUID */ - wsrep_seqno_t seqno; /*!< Sequence number */ -} wsrep_gtid_t; - -/*! Undefined GTID */ -static const wsrep_gtid_t WSREP_GTID_UNDEFINED = {{{0, }}, -1}; - -/*! Minimum number of bytes guaranteed to store GTID string representation, - * terminating '\0' not included (36 + 1 + 20) */ -#define WSREP_GTID_STR_LEN 57 - - -/*! - * Scan GTID from string - * @return length of GTID string representation or negative error code - */ -extern int -wsrep_gtid_scan(const char* str, size_t str_len, wsrep_gtid_t* gtid); - -/*! - * Print GTID to string - * @return length of GTID string representation or negative error code - */ -extern int -wsrep_gtid_print(const wsrep_gtid_t* gtid, char* str, size_t str_len); - - -/*! - * Transaction meta data - */ -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_trx_meta_t; - - -/*! - * member status - */ -typedef enum wsrep_member_status { - WSREP_MEMBER_UNDEFINED, //!< undefined state - WSREP_MEMBER_JOINER, //!< incomplete state, requested state transfer - WSREP_MEMBER_DONOR, //!< complete state, donates state transfer - WSREP_MEMBER_JOINED, //!< complete state - WSREP_MEMBER_SYNCED, //!< complete state, synchronized with group - WSREP_MEMBER_ERROR, //!< this and above is provider-specific error code - WSREP_MEMBER_MAX -} wsrep_member_status_t; - -/*! - * static information about a group member (some fields are tentative yet) - */ -typedef struct wsrep_member_info { - wsrep_uuid_t id; //!< group-wide unique member ID - char name[WSREP_MEMBER_NAME_LEN]; //!< human-readable name - char incoming[WSREP_INCOMING_LEN]; //!< address for client requests -} wsrep_member_info_t; - -/*! - * group status - */ -typedef enum wsrep_view_status { - WSREP_VIEW_PRIMARY, //!< primary group configuration (quorum present) - WSREP_VIEW_NON_PRIMARY, //!< non-primary group configuration (quorum lost) - WSREP_VIEW_DISCONNECTED, //!< not connected to group, retrying. - WSREP_VIEW_MAX -} wsrep_view_status_t; - -/*! - * view of the group - */ -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 - 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; - -/*! - * 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. - */ -#define WSREP_STATE_TRANSFER_TRIVIAL "trivial" - -/*! - * 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. - */ -#define WSREP_STATE_TRANSFER_NONE "none" - -/*! - * @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. If view info indicates existence of discontinuity - * between group and member states, state transfer request message - * should be filled in by the callback implementation. - * - * @note Currently it is assumed that sst_req is allocated using - * malloc()/calloc()/realloc() and it will be freed by - * wsrep implementation. - * - * @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 -); - - -/*! - * @brief apply callback - * - * 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 - * - * @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 - */ -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 -); - - -/*! - * @brief unordered callback - * - * This handler is called to execute unordered actions (actions that need not - * to be executed in any particular order) attached to writeset. - * - * @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 -); - - -/*! - * @brief a callback to donate state snapshot - * - * This handler is called from wsrep library when it needs this node - * to deliver state to a new cluster member. - * No state changes will be committed for the duration of this call. - * Wsrep implementation may provide internal state to be transmitted - * to new cluster member for initial state. - * - * @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 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_gtid_t* state_id, - const char* state, - size_t state_len, - wsrep_bool_t bypass -); - - -/*! - * @brief a callback to signal application that wsrep state is synced - * with cluster - * - * This callback is called after wsrep library has got in sync with - * rest of the cluster. - * - * @param app_ctx application context - */ -typedef void (*wsrep_synced_cb_t) (void* app_ctx); - - -/*! - * Initialization parameters for wsrep provider. - */ -struct wsrep_init_args -{ - void* app_ctx; //!< Application context for callbacks - - /* Configuration parameters */ - const char* node_name; //!< Symbolic name of this node (e.g. hostname) - const char* node_address; //!< Address to be used by wsrep provider - const char* node_incoming; //!< Address for incoming client connections - const char* data_dir; //!< Directory where wsrep files are kept if any - const char* options; //!< Provider-specific configuration string - int proto_ver; //!< Max supported application protocol version - - /* 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 - - /* Application callbacks */ - wsrep_log_cb_t logger_cb; //!< logging handler - wsrep_view_cb_t view_handler_cb; //!< group view change handler - - /* 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 - - /* State Snapshot Transfer callbacks */ - wsrep_sst_donate_cb_t sst_donate_cb; //!< starting to donate - wsrep_synced_cb_t synced_cb; //!< synced with group -}; - - -/*! Type of the stats variable value in struct wsrep_status_var */ -typedef enum wsrep_var_type -{ - WSREP_VAR_STRING, //!< pointer to null-terminated string - WSREP_VAR_INT64, //!< int64_t - WSREP_VAR_DOUBLE //!< double -} -wsrep_var_type_t; - -/*! Generalized stats variable representation */ -struct wsrep_stats_var -{ - const char* name; //!< variable name - wsrep_var_type_t type; //!< variable value type - union { - int64_t _integer64; - 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 -{ - const wsrep_buf_t* key_parts; /*!< Array of key parts */ - size_t key_parts_num; /*!< Number of key parts */ -} wsrep_key_t; - -/*! Key type: - * EXCLUSIVE conflicts with any key type - * SEMI reserved. If not supported, should be interpeted as EXCLUSIVE - * SHARED conflicts only with EXCLUSIVE keys */ -typedef enum wsrep_key_type -{ - WSREP_KEY_SHARED = 0, - WSREP_KEY_SEMI, - WSREP_KEY_EXCLUSIVE -} wsrep_key_type_t; - -/*! Data type: - * ORDERED state modification event that should be applied and committed - * in order. - * UNORDERED some action that does not modify state and execution of which is - * optional and does not need to happen in order. - * ANNOTATION (human readable) writeset annotation. */ -typedef enum wsrep_data_type -{ - WSREP_DATA_ORDERED = 0, - WSREP_DATA_UNORDERED, - WSREP_DATA_ANNOTATION -} 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 - * - * Instead of passing wsrep_ws_handle_t directly to wsrep calls, - * wrapping handle with this call offloads bookkeeping from - * application. - */ -static inline wsrep_ws_handle_t* wsrep_ws_handle_for_trx( - wsrep_ws_handle_t* ws_handle, - wsrep_trx_id_t trx_id) -{ - if (ws_handle->trx_id != trx_id) - { - ws_handle->trx_id = trx_id; - ws_handle->opaque = NULL; - } - return ws_handle; -} - - -/*! - * A handle for processing preordered actions. - * Must be initialized to WSREP_PO_INITIALIZER before use. - */ -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; -/*! - * wsrep interface for dynamically loadable libraries - */ -struct wsrep { - - const char *version; //!< interface version string - - /*! - * @brief Initializes wsrep provider - * - * @param wsrep provider handle - * @param args wsrep initialization parameters - */ - wsrep_status_t (*init) (wsrep_t* wsrep, - const struct wsrep_init_args* args); - - /*! - * @brief Returns provider capabilities flag bitmap - * - * @param wsrep provider handle - */ - uint64_t (*capabilities) (wsrep_t* wsrep); - - /*! - * @brief Passes provider-specific configuration string to provider. - * - * @param wsrep provider handle - * @param conf configuration string - * - * @retval WSREP_OK configuration string was parsed successfully - * @retval WSREP_WARNING could't not parse conf string, no action taken - */ - wsrep_status_t (*options_set) (wsrep_t* wsrep, const char* conf); - - /*! - * @brief Returns provider-specific string with current configuration values. - * - * @param wsrep provider handle - * - * @return a dynamically allocated string with current configuration - * parameter values - */ - char* (*options_get) (wsrep_t* wsrep); - - /*! - * @brief Opens connection to cluster - * - * Returns when either node is ready to operate as a part of the clsuter - * or fails to reach operating status. - * - * @param wsrep provider handle - * @param cluster_name unique symbolic cluster name - * @param cluster_url URL-like cluster address (backend://address) - * @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 - * parameters, like backend spec and/or listen address. - */ - wsrep_status_t (*connect) (wsrep_t* wsrep, - const char* cluster_name, - const char* cluster_url, - const char* state_donor, - wsrep_bool_t bootstrap); - - /*! - * @brief Closes connection to cluster. - * - * If state_uuid and/or state_seqno is not NULL, will store final state - * in there. - * - * @param wsrep this wsrep handler - */ - wsrep_status_t (*disconnect)(wsrep_t* wsrep); - - /*! - * @brief start receiving replication events - * - * This function never returns - * - * @param wsrep provider handle - * @param recv_ctx receiver context - */ - wsrep_status_t (*recv)(wsrep_t* wsrep, void* recv_ctx); - - /*! - * @brief Replicates/logs result of transaction to other nodes and allocates - * required resources. - * - * 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. - * - * @param wsrep provider handle - * @param ws_handle writeset of committing transaction - * @param conn_id connection ID - * @param flags fine tuning the replication WSREP_FLAG_* - * @param meta transaction meta data - * - * @retval WSREP_OK cluster-wide commit succeeded - * @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); - - /*! - * @brief Releases resources after transaction commit. - * - * Ends commit critical section. - * - * @param wsrep provider handle - * @param ws_handle writeset of committing transaction - * @retval WSREP_OK post_commit succeeded - */ - wsrep_status_t (*post_commit) (wsrep_t* wsrep, - wsrep_ws_handle_t* ws_handle); - - /*! - * @brief Releases resources after transaction rollback. - * - * @param wsrep provider handle - * @param ws_handle writeset of committing transaction - * @retval WSREP_OK post_rollback succeeded - */ - wsrep_status_t (*post_rollback)(wsrep_t* wsrep, - wsrep_ws_handle_t* ws_handle); - - /*! - * @brief Replay trx as a slave writeset - * - * If local trx has been aborted by brute force, and it has already - * replicated before this abort, we must try if we can apply it as - * slave trx. Note that slave nodes see only trx writesets and certification - * test based on write set content can be different to DBMS lock conflicts. - * - * @param wsrep provider handle - * @param ws_handle writeset of committing transaction - * @param trx_ctx transaction context - * - * @retval WSREP_OK cluster commit succeeded - * @retval WSREP_TRX_FAIL must rollback transaction - * @retval WSREP_BF_ABORT brute force abort happened after trx replicated - * must rollback transaction and try to replay - * @retval WSREP_CONN_FAIL must close client connection - * @retval WSREP_NODE_FAIL must close all connections and reinit - */ - wsrep_status_t (*replay_trx)(wsrep_t* wsrep, - wsrep_ws_handle_t* ws_handle, - void* trx_ctx); - - /*! - * @brief Abort pre_commit() 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. - * - * The kill routine checks that abort is not attmpted against a transaction - * which is front of the caller (in total order). - * - * @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 - * - * @retval WSREP_OK abort secceded - * @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); - - /*! - * @brief Appends a row reference to transaction writeset - * - * Both copy flag and key_type can be ignored by provider (key type - * interpreted as WSREP_KEY_EXCLUSIVE). - * - * @param wsrep provider handle - * @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 copy can be set to FALSE if keys persist through commit. - */ - wsrep_status_t (*append_key)(wsrep_t* wsrep, - wsrep_ws_handle_t* ws_handle, - const wsrep_key_t* keys, - size_t count, - enum wsrep_key_type type, - wsrep_bool_t copy); - - /*! - * @brief Appends data to transaction writeset - * - * This method can be called any time before commit and it - * appends a number of data buffers to transaction writeset. - * - * Both copy and unordered flags can be ignored by provider. - * - * @param wsrep provider handle - * @param ws_handle writeset handle - * @param data array of data buffers - * @param count buffer count - * @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); - - /*! - * @brief Get causal ordering for read operation - * - * 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. - * - * @param wsrep provider handle - * @param gtid location to store GTID - */ - wsrep_status_t (*causal_read)(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 - * closing. - * - * @param wsrep provider handle - * @param conn_id connection ID - * @param query the 'set database' query - * @param query_len length of query (does not end with 0) - */ - wsrep_status_t (*free_connection)(wsrep_t* wsrep, - wsrep_conn_id_t conn_id); - - /*! - * @brief Replicates a query and starts "total order isolation" section. - * - * Replicates the action spec and returns success code, which caller must - * check. Total order isolation continues until to_execute_end() is called. - * - * @param wsrep provider handle - * @param conn_id connection ID - * @param keys array of keys - * @param keys_num lenght of the array of keys - * @param action action buffer array to be executed - * @param count action buffer count - * @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); - - /*! - * @brief Ends the total order isolation section. - * - * 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 conn_id connection ID - * - * @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); - - /*! - * @brief Collects preordered replication events into a writeset. - * - * @param wsrep wsrep provider handle - * @param handle a handle associated with a given writeset - * @param data an array of data buffers. - * @param count length of data buffer array. - * @param copy whether provider needs to make a copy of events. - * - * @retval WSREP_OK cluster-wide commit succeeded - * @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); - - /*! - * @brief "Commits" preordered writeset to cluster. - * - * The contract is that the writeset will be committed in the same (partial) - * order this method was called. Frees resources associated with the writeset - * handle and reinitializes the handle. - * - * @param wsrep wsrep provider handle - * @param po_handle a handle associated with a given writeset - * @param source_id ID of the event producer, also serves as the partial order - * or stream ID - events with different source_ids won't be - * ordered with respect to each other. - * @param flags WSREP_FLAG_... flags - * @param pa_range the number of preceding events this event can be processed - * in parallel with. A value of 0 means strict serial - * processing. Note: commits always happen in wsrep order. - * @param commit 'true' to commit writeset to cluster (replicate) or - * 'false' to rollback (cancel) the writeset. - * - * @retval WSREP_OK cluster-wide commit succeeded - * @retval WSREP_TRX_FAIL operation failed (e.g. NON-PRIMARY component) - * @retval WSREP_NODE_FAIL must close all connections and reinit - */ - wsrep_status_t (*preordered_commit) (wsrep_t* wsrep, - wsrep_po_handle_t* handle, - const wsrep_uuid_t* source_id, - uint32_t flags, - int pa_range, - wsrep_bool_t commit); - - /*! - * @brief Signals to wsrep provider that state snapshot has been sent to - * joiner. - * - * @param wsrep provider handle - * @param state_id state ID - * @param rcode 0 or negative error code of the operation. - */ - wsrep_status_t (*sst_sent)(wsrep_t* wsrep, - const wsrep_gtid_t* state_id, - int rcode); - - /*! - * @brief Signals to wsrep provider that new state snapshot has been received. - * May deadlock if called from sst_prepare_cb. - * - * @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, - int rcode); - - - /*! - * @brief Generate request for consistent snapshot. - * - * If successfull, 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 - * from callback. - * - * @param wsrep provider handle - * @param msg context message for SST donate callback - * @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); - - /*! - * @brief Returns an array fo status variables. - * Array is terminated by Null variable name. - * - * @param wsrep provider handle - * @return array of struct wsrep_status_var. - */ - struct wsrep_stats_var* (*stats_get) (wsrep_t* wsrep); - - /*! - * @brief Release resources that might be associated with the array. - * - * @param wsrep provider handle. - * @param var_array array returned by stats_get(). - */ - void (*stats_free) (wsrep_t* wsrep, struct wsrep_stats_var* var_array); - - /*! - * @brief Reset some stats variables to inital value, provider-dependent. - * - * @param wsrep provider handle. - */ - void (*stats_reset) (wsrep_t* wsrep); - - /*! - * @brief Pauses writeset applying/committing. - * - * @return global sequence number of the paused state or negative error code. - */ - wsrep_seqno_t (*pause) (wsrep_t* wsrep); - - /*! - * @brief Resumes writeset applying/committing. - */ - wsrep_status_t (*resume) (wsrep_t* wsrep); - - /*! - * @brief Desynchronize from cluster - * - * Effectively turns off flow control for this node, allowing it - * to fall behind the cluster. - */ - wsrep_status_t (*desync) (wsrep_t* wsrep); - - /*! - * @brief Request to resynchronize with cluster. - * - * Effectively turns on flow control. Asynchronous - actual synchronization - * event to be deliverred via sync_cb. - */ - wsrep_status_t (*resync) (wsrep_t* wsrep); - - /*! - * @brief Acquire global named lock - * - * @param wsrep wsrep provider handle - * @param name lock name - * @param shared shared or exclusive lock - * @param owner 64-bit owner ID - * @param tout timeout in nanoseconds. - * 0 - return immediately, -1 wait forever. - * @return wsrep status or negative error code - * @retval -EDEADLK lock was already acquired by this thread - * @retval -EBUSY lock was busy - */ - wsrep_status_t (*lock) (wsrep_t* wsrep, - const char* name, wsrep_bool_t shared, - uint64_t owner, int64_t tout); - - /*! - * @brief Release global named lock - * - * @param wsrep wsrep provider handle - * @param name lock name - * @param owner 64-bit owner ID - * @return wsrep status or negative error code - * @retval -EPERM lock does not belong to this owner - */ - wsrep_status_t (*unlock) (wsrep_t* wsrep, const char* name, uint64_t owner); - - /*! - * @brief Check if global named lock is locked - * - * @param wsrep wsrep provider handle - * @param name lock name - * @param owner if not NULL will contain 64-bit owner ID - * @param node if not NULL will contain owner's node UUID - * @return true if lock is locked - */ - wsrep_bool_t (*is_locked) (wsrep_t* wsrep, const char* name, uint64_t* conn, - wsrep_uuid_t* node); - - /*! - * wsrep provider name - */ - const char* provider_name; - - /*! - * wsrep provider version - */ - const char* provider_version; - - /*! - * wsrep provider vendor name - */ - const char* provider_vendor; - - /*! - * @brief Frees allocated resources before unloading the library. - * @param wsrep provider handle - */ - void (*free)(wsrep_t* wsrep); - - void *dlh; //!< reserved for future use - void *ctx; //!< reserved for implemetation private context -}; - - -/*! - * - * @brief Loads wsrep library - * - * @param spec path to wsrep library. If NULL or WSREP_NONE initialises dummy - * pass-through implementation. - * @param hptr wsrep handle - * @param log_cb callback to handle loader messages. Otherwise writes to stderr. - * - * @return zero on success, errno on failure - */ -int wsrep_load(const char* spec, wsrep_t** hptr, wsrep_log_cb_t log_cb); - -/*! - * @brief Unloads wsrep library and frees associated resources - * - * @param hptr wsrep handler pointer - */ -void wsrep_unload(wsrep_t* hptr); - -#ifdef __cplusplus -} -#endif - -#endif /* WSREP_H */ diff --git a/wsrep/wsrep_dummy.c b/wsrep/wsrep_dummy.c deleted file mode 100644 index e48dcff39a1..00000000000 --- a/wsrep/wsrep_dummy.c +++ /dev/null @@ -1,413 +0,0 @@ -/* Copyright (C) 2009-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -/*! @file Dummy wsrep API implementation. */ - -#include "wsrep_api.h" - -#include <errno.h> -#include <string.h> - -/*! Dummy backend context. */ -typedef struct wsrep_dummy -{ - wsrep_log_cb_t log_fn; - char* options; -} wsrep_dummy_t; - -/* Get pointer to wsrep_dummy context from wsrep_t pointer */ -#define WSREP_DUMMY(_p) ((wsrep_dummy_t *) (_p)->ctx) - -/* Trace function usage a-la DBUG */ -#define WSREP_DBUG_ENTER(_w) do { \ - if (WSREP_DUMMY(_w)) { \ - if (WSREP_DUMMY(_w)->log_fn) \ - WSREP_DUMMY(_w)->log_fn(WSREP_LOG_DEBUG, __FUNCTION__); \ - } \ - } while (0) - - -static void dummy_free(wsrep_t *w) -{ - WSREP_DBUG_ENTER(w); - if (WSREP_DUMMY(w)->options) { - free(WSREP_DUMMY(w)->options); - WSREP_DUMMY(w)->options = NULL; - } - free(w->ctx); - w->ctx = NULL; -} - -static wsrep_status_t dummy_init (wsrep_t* w, - const struct wsrep_init_args* args) -{ - WSREP_DUMMY(w)->log_fn = args->logger_cb; - WSREP_DBUG_ENTER(w); - if (args->options) { - WSREP_DUMMY(w)->options = strdup(args->options); - } - return WSREP_OK; -} - -static uint64_t dummy_capabilities (wsrep_t* w __attribute__((unused))) -{ - return 0; -} - -static wsrep_status_t dummy_options_set( - wsrep_t* w, - const char* conf) -{ - WSREP_DBUG_ENTER(w); - if (WSREP_DUMMY(w)->options) { - free(WSREP_DUMMY(w)->options); - WSREP_DUMMY(w)->options = NULL; - } - if (conf) { - WSREP_DUMMY(w)->options = strdup(conf); - } - return WSREP_OK; -} - -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; -} - -static wsrep_status_t dummy_connect( - wsrep_t* w, - const char* name __attribute__((unused)), - const char* url __attribute__((unused)), - const char* donor __attribute__((unused)), - wsrep_bool_t bootstrap __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_disconnect(wsrep_t* w) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_recv(wsrep_t* w, - void* recv_ctx __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_pre_commit( - wsrep_t* w, - const wsrep_conn_id_t conn_id __attribute__((unused)), - wsrep_ws_handle_t* ws_handle __attribute__((unused)), - uint32_t flags __attribute__((unused)), - wsrep_trx_meta_t* meta __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_post_commit( - wsrep_t* w, - wsrep_ws_handle_t* ws_handle __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_post_rollback( - wsrep_t* w, - wsrep_ws_handle_t* ws_handle __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_replay_trx( - wsrep_t* w, - wsrep_ws_handle_t* ws_handle __attribute__((unused)), - void* trx_ctx __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_abort_pre_commit( - wsrep_t* w, - const wsrep_seqno_t bf_seqno __attribute__((unused)), - const wsrep_trx_id_t trx_id __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_append_key( - wsrep_t* w, - wsrep_ws_handle_t* ws_handle __attribute__((unused)), - 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))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_append_data( - wsrep_t* w, - wsrep_ws_handle_t* ws_handle __attribute__((unused)), - 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))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_causal_read( - wsrep_t* w, - wsrep_gtid_t* gtid __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_free_connection( - wsrep_t* w, - const wsrep_conn_id_t conn_id __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_to_execute_start( - wsrep_t* w, - const wsrep_conn_id_t conn_id __attribute__((unused)), - const wsrep_key_t* key __attribute__((unused)), - const size_t key_num __attribute__((unused)), - const struct wsrep_buf* data __attribute__((unused)), - const size_t count __attribute__((unused)), - wsrep_trx_meta_t* meta __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_to_execute_end( - wsrep_t* w, - const wsrep_conn_id_t conn_id __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_preordered_collect( - wsrep_t* w, - wsrep_po_handle_t* handle __attribute__((unused)), - const struct wsrep_buf* data __attribute__((unused)), - size_t count __attribute__((unused)), - wsrep_bool_t copy __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_preordered_commit( - wsrep_t* w, - wsrep_po_handle_t* handle __attribute__((unused)), - const wsrep_uuid_t* source_id __attribute__((unused)), - uint32_t flags __attribute__((unused)), - int pa_range __attribute__((unused)), - wsrep_bool_t commit __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_sst_sent( - wsrep_t* w, - const wsrep_gtid_t* state_id __attribute__((unused)), - const int rcode __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -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 int rcode __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -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))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static struct wsrep_stats_var dummy_stats[] = { - { NULL, WSREP_VAR_STRING, { 0 } } -}; - -static struct wsrep_stats_var* dummy_stats_get (wsrep_t* w) -{ - WSREP_DBUG_ENTER(w); - return dummy_stats; -} - -static void dummy_stats_free ( - wsrep_t* w, - struct wsrep_stats_var* stats __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); -} - -static void dummy_stats_reset (wsrep_t* w) -{ - WSREP_DBUG_ENTER(w); -} - -static wsrep_seqno_t dummy_pause (wsrep_t* w) -{ - WSREP_DBUG_ENTER(w); - return -ENOSYS; -} - -static wsrep_status_t dummy_resume (wsrep_t* w) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_desync (wsrep_t* w) -{ - WSREP_DBUG_ENTER(w); - return WSREP_NOT_IMPLEMENTED; -} - -static wsrep_status_t dummy_resync (wsrep_t* w) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -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))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_NOT_IMPLEMENTED; -} - -static wsrep_status_t dummy_unlock (wsrep_t* w, - const char* s __attribute__((unused)), - uint64_t o __attribute__((unused))) -{ - WSREP_DBUG_ENTER(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))) -{ - WSREP_DBUG_ENTER(w); - return 0; -} - -static wsrep_t dummy_iface = { - WSREP_INTERFACE_VERSION, - &dummy_init, - &dummy_capabilities, - &dummy_options_set, - &dummy_options_get, - &dummy_connect, - &dummy_disconnect, - &dummy_recv, - &dummy_pre_commit, - &dummy_post_commit, - &dummy_post_rollback, - &dummy_replay_trx, - &dummy_abort_pre_commit, - &dummy_append_key, - &dummy_append_data, - &dummy_causal_read, - &dummy_free_connection, - &dummy_to_execute_start, - &dummy_to_execute_end, - &dummy_preordered_collect, - &dummy_preordered_commit, - &dummy_sst_sent, - &dummy_sst_received, - &dummy_snapshot, - &dummy_stats_get, - &dummy_stats_free, - &dummy_stats_reset, - &dummy_pause, - &dummy_resume, - &dummy_desync, - &dummy_resync, - &dummy_lock, - &dummy_unlock, - &dummy_is_locked, - WSREP_NONE, - WSREP_INTERFACE_VERSION, - "Codership Oy <info@codership.com>", - &dummy_free, - NULL, - NULL -}; - -int wsrep_dummy_loader(wsrep_t* w) -{ - if (!w) - return EINVAL; - - *w = dummy_iface; - - // allocate private context - if (!(w->ctx = malloc(sizeof(wsrep_dummy_t)))) - return ENOMEM; - - // initialize private context - WSREP_DUMMY(w)->log_fn = NULL; - WSREP_DUMMY(w)->options = NULL; - - return 0; -} diff --git a/wsrep/wsrep_gtid.c b/wsrep/wsrep_gtid.c deleted file mode 100644 index 45148785c25..00000000000 --- a/wsrep/wsrep_gtid.c +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -/*! @file Helper functions to deal with GTID string representations */ - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <inttypes.h> - -#include "wsrep_api.h" - -/*! - * Read GTID from string - * @return length of GTID string representation or -EINVAL in case of error - */ -int -wsrep_gtid_scan(const char* str, size_t str_len, wsrep_gtid_t* gtid) -{ - unsigned int offset; - char* endptr; - - if ((offset = wsrep_uuid_scan(str, str_len, >id->uuid)) > 0 && - offset < str_len && str[offset] == ':') { - ++offset; - if (offset < str_len) - { - errno = 0; - gtid->seqno = strtoll(str + offset, &endptr, 0); - - if (errno == 0) { - offset = endptr - str; - return offset; - } - } - } - *gtid = WSREP_GTID_UNDEFINED; - return -EINVAL; -} - -/*! - * Write GTID to string - * @return length of GTID stirng representation of -EMSGSIZE if string is too - * short - */ -int -wsrep_gtid_print(const wsrep_gtid_t* gtid, char* str, size_t str_len) -{ - unsigned int offset, ret; - if ((offset = wsrep_uuid_print(>id->uuid, str, str_len)) > 0) - { - ret = snprintf(str + offset, str_len - offset, - ":%" PRId64, gtid->seqno); - if (ret <= str_len - offset) { - return (offset + ret); - } - - } - - return -EMSGSIZE; -} diff --git a/wsrep/wsrep_loader.c b/wsrep/wsrep_loader.c deleted file mode 100644 index 1321538742f..00000000000 --- a/wsrep/wsrep_loader.c +++ /dev/null @@ -1,226 +0,0 @@ -/* Copyright (C) 2009-2011 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -/*! @file wsrep implementation loader */ - -#include <dlfcn.h> -#include <errno.h> -#include <string.h> -#include <stdio.h> - -#include "wsrep_api.h" - -// Logging stuff for the loader -static const char* log_levels[] = {"FATAL", "ERROR", "WARN", "INFO", "DEBUG"}; - -static void default_logger (wsrep_log_level_t lvl, const char* msg) -{ - fprintf (stderr, "wsrep loader: [%s] %s\n", log_levels[lvl], msg); -} - -static wsrep_log_cb_t logger = default_logger; - -/************************************************************************** - * Library loader - **************************************************************************/ - -static int wsrep_check_iface_version(const char* found, const char* iface_ver) -{ - const size_t msg_len = 128; - char msg[128]; - - if (strcmp(found, iface_ver)) { - snprintf (msg, msg_len, - "provider interface version mismatch: need '%s', found '%s'", - iface_ver, found); - logger (WSREP_LOG_ERROR, msg); - return EINVAL; - } - - return 0; -} - -static int verify(const wsrep_t *wh, const char *iface_ver) -{ - char msg[128]; - -#define VERIFY(_p) if (!(_p)) { \ - snprintf(msg, sizeof(msg), "wsrep_load(): verify(): %s\n", # _p); \ - logger (WSREP_LOG_ERROR, msg); \ - return EINVAL; \ - } - - VERIFY(wh); - VERIFY(wh->version); - - if (wsrep_check_iface_version(wh->version, iface_ver)) - return EINVAL; - - VERIFY(wh->init); - VERIFY(wh->options_set); - VERIFY(wh->options_get); - VERIFY(wh->connect); - VERIFY(wh->disconnect); - VERIFY(wh->recv); - VERIFY(wh->pre_commit); - VERIFY(wh->post_commit); - VERIFY(wh->post_rollback); - VERIFY(wh->replay_trx); - VERIFY(wh->abort_pre_commit); - VERIFY(wh->append_key); - VERIFY(wh->append_data); - VERIFY(wh->free_connection); - VERIFY(wh->to_execute_start); - VERIFY(wh->to_execute_end); - VERIFY(wh->preordered_collect); - VERIFY(wh->preordered_commit); - VERIFY(wh->sst_sent); - VERIFY(wh->sst_received); - VERIFY(wh->stats_get); - VERIFY(wh->stats_free); - VERIFY(wh->stats_reset); - VERIFY(wh->pause); - VERIFY(wh->resume); - VERIFY(wh->desync); - VERIFY(wh->resync); - VERIFY(wh->lock); - VERIFY(wh->unlock); - VERIFY(wh->is_locked); - VERIFY(wh->provider_name); - VERIFY(wh->provider_version); - VERIFY(wh->provider_vendor); - VERIFY(wh->free); - return 0; -} - -typedef int (*wsrep_loader_fun)(wsrep_t*); - -static wsrep_loader_fun wsrep_dlf(void *dlh, const char *sym) -{ - union { - wsrep_loader_fun dlfun; - void *obj; - } alias; - alias.obj = dlsym(dlh, sym); - return alias.dlfun; -} - -static int wsrep_check_version_symbol(void *dlh) -{ - char** dlversion = NULL; - dlversion = (char**) dlsym(dlh, "wsrep_interface_version"); - if (dlversion == NULL) - return 0; - return wsrep_check_iface_version(*dlversion, WSREP_INTERFACE_VERSION); -} - -extern int wsrep_dummy_loader(wsrep_t *w); - -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; - - if (NULL != log_cb) - logger = log_cb; - - if (!(spec && hptr)) - return EINVAL; - - snprintf (msg, sizeof(msg)-1, - "wsrep_load(): loading provider library '%s'", spec); - logger (WSREP_LOG_INFO, msg); - - if (!(*hptr = malloc(sizeof(wsrep_t)))) { - logger (WSREP_LOG_FATAL, "wsrep_load(): out of memory"); - return ENOMEM; - } - - if (!spec || strcmp(spec, WSREP_NONE) == 0) { - if ((ret = wsrep_dummy_loader(*hptr)) != 0) { - free (*hptr); - *hptr = NULL; - } - return ret; - } - - if (!(dlh = dlopen(spec, RTLD_NOW | RTLD_LOCAL))) { - snprintf(msg, sizeof(msg)-1, "wsrep_load(): dlopen(): %s", dlerror()); - logger (WSREP_LOG_ERROR, msg); - ret = EINVAL; - goto out; - } - - if (!(dlfun = wsrep_dlf(dlh, "wsrep_loader"))) { - ret = EINVAL; - goto out; - } - - if (wsrep_check_version_symbol(dlh) != 0) { - ret = EINVAL; - goto out; - } - - if ((ret = (*dlfun)(*hptr)) != 0) { - snprintf(msg, sizeof(msg)-1, "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, - "wsrep_load(): interface version mismatch: my version %s, " - "provider version %s", WSREP_INTERFACE_VERSION, - (*hptr)->version); - logger (WSREP_LOG_ERROR, msg); - goto out; - } - - (*hptr)->dlh = dlh; - -out: - if (ret != 0) { - if (dlh) dlclose(dlh); - free(*hptr); - *hptr = NULL; - } else { - snprintf (msg, sizeof(msg)-1, - "wsrep_load(): %s %s by %s loaded successfully.", - (*hptr)->provider_name, (*hptr)->provider_version, - (*hptr)->provider_vendor); - logger (WSREP_LOG_INFO, msg); - } - - return ret; -} - -void wsrep_unload(wsrep_t *hptr) -{ - if (!hptr) { - logger (WSREP_LOG_WARN, "wsrep_unload(): null pointer."); - } else { - if (hptr->free) - hptr->free(hptr); - if (hptr->dlh) - dlclose(hptr->dlh); - free(hptr); - } -} - diff --git a/wsrep/wsrep_uuid.c b/wsrep/wsrep_uuid.c deleted file mode 100644 index 54ae4ab5ed5..00000000000 --- a/wsrep/wsrep_uuid.c +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright (C) 2009 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -/*! @file Helper functions to deal with history UUID string representations */ - -#include <errno.h> -#include <ctype.h> -#include <stdio.h> - -#include "wsrep_api.h" - -/*! - * Read UUID from string - * @return length of UUID string representation or -EINVAL in case of error - */ -int -wsrep_uuid_scan (const char* str, size_t str_len, wsrep_uuid_t* uuid) -{ - unsigned int uuid_len = 0; - unsigned int uuid_offt = 0; - - while (uuid_len + 1 < str_len) { - /* We are skipping potential '-' after uuid_offt == 4, 6, 8, 10 - * which means - * (uuid_offt >> 1) == 2, 3, 4, 5, - * which in turn means - * (uuid_offt >> 1) - 2 <= 3 - * since it is always >= 0, because uuid_offt is unsigned */ - if (((uuid_offt >> 1) - 2) <= 3 && str[uuid_len] == '-') { - // skip dashes after 4th, 6th, 8th and 10th positions - uuid_len += 1; - continue; - } - - if (isxdigit(str[uuid_len]) && isxdigit(str[uuid_len + 1])) { - // got hex digit, scan another byte to uuid, increment uuid_offt - sscanf (str + uuid_len, "%2hhx", uuid->data + uuid_offt); - uuid_len += 2; - uuid_offt += 1; - if (sizeof (uuid->data) == uuid_offt) - return uuid_len; - } - else { - break; - } - } - - *uuid = WSREP_UUID_UNDEFINED; - return -EINVAL; -} - -/*! - * Write UUID to string - * @return length of UUID string representation or -EMSGSIZE if string is too - * short - */ -int -wsrep_uuid_print (const wsrep_uuid_t* uuid, char* str, size_t str_len) -{ - if (str_len > 36) { - const unsigned char* u = uuid->data; - return snprintf(str, str_len, "%02x%02x%02x%02x-%02x%02x-%02x%02x-" - "%02x%02x-%02x%02x%02x%02x%02x%02x", - u[ 0], u[ 1], u[ 2], u[ 3], u[ 4], u[ 5], u[ 6], u[ 7], - u[ 8], u[ 9], u[10], u[11], u[12], u[13], u[14], u[15]); - } - else { - return -EMSGSIZE; - } -} |